#include <stdio.h>
void*** Dio=NULL;
struct S
{
int poz;
int neg;
};
void readmatrix(int N, int M, int A[N][M], FILE* fp)
{
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
{
fscanf(fp, "%d ", &A[i][j]);
}
}
}
void testmatrix(int N, int M, int A[N][M])
{
printf("\n");
for(int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
printf("%d ", A[i][j]);
printf("\n");
}
}
void swap(int N, int M, int A[N][M], int k, int type)
{
if (type == 0) // then switch line
for (int j = 0; j < M; ++j) A[k][j] *= -1;
if (type == 1) // then switch column
for (int i = 0; i < N; ++i) A[i][k] *= -1;
}
int sum(int N, int M, int A[N][M])
{
int sum = 0;
for (int i = 0; i < N; ++i)
for (int j = 0; j < M; ++j)
sum += A[i][j];
return sum;
}
// stuff for I,J
void clearout(int N, int M, int I[N], int J[M])
{
for (int i = 0; i < N; ++i)
I[i] = 0;
for (int j = 0; j < M; ++j)
J[j] = 0;
}
void printout(int size, int A[size], int type)
{
if (type == 0) // then print line flag
{
printf("I = ");
for (int i = 0; i < size; ++i)
printf("%d ", A[i]);
printf("\n");
}
if (type == 1) // then print column flag
{
printf("J = ");
for (int i = 0; i < size; ++i)
printf("%d ", A[i]);
printf("\n");
}
}
int main()
{
FILE* fp;
fp = fopen("flip.in", "r");
int N, M;
fscanf(fp, "%d %d", &N, &M);
int A[N][M];
readmatrix(N, M, A, fp);
//////////////////////////////
///* ACTUAL RELEVANT CODE *///
//////////////////////////////
// initialise structure values
struct S Lin[N], Col[M];
for (int i = 0; i < N; ++i) Lin[i].poz = Lin[i].neg = 0;
for (int j = 0; j < M; ++j) Col[j].poz = Col[j].neg = 0;
//flip recorder
int I[N];
int J[M];
// flag
int flag = 1;
// fill up Lin, Col
for (int i = 0; i < N; ++i)
for (int j = 0; j < M; ++j)
if (A[i][j] > 0)
{
Lin[i].poz += A[i][j];
Col[j].poz += A[i][j];
}
else if (A[i][j] < 0)
{
Lin[i].neg -= A[i][j];
Col[j].neg -= A[i][j];
}
// fill up I
for (int i = 0; i < N; ++i)
if (Lin[i].poz < Lin[i].neg) I[i] = 1;
else I[i] = 0;
// fill up J
for (int j = 0; j < M; ++j)
if (Col[j].poz < Col[j].neg) J[j] = 1;
else J[j] = 0;
//printout(N, I, 0);
//printout(M, J, 1);
while (flag)
{
flag = 0;
// find maximum change in lines
int linmax = 0, l = -1;
for (int i = 0; i < N; ++i)
if (I[i] && ((Lin[i].neg - Lin[i].poz) > linmax))
{
linmax = Lin[i].neg - Lin[i].poz;
l = i;
}
// find maximum change in cols
int colmax = 0, c = -1;
for (int j = 0; j < M; ++j)
if (J[j] && ((Col[j].neg - Col[j].poz) > colmax))
{
colmax = Col[j].neg - Col[j].poz;
c = j;
}
/* !!! linmax == 0 se I[i] == 0 per qualsiasi i = 1...N !!! */
// swap the biggest value
if (linmax >= colmax && (linmax != 0)) // la diff e 0 iff non e stata modificata
{
swap(N,M,A,l,0);
// on lines
int aux = Lin[l].neg;
Lin[l].neg = Lin[l].poz;
Lin[l].poz = aux;
I[l] = 0;
// on cols
for (int j = 0; j < M; ++j) // for each col
{
// if A[l][j] > 0 then before the switch it was < 0, but
// verification is superfluos because fo the sign (- * - = +)
Col[j].poz += A[l][j];
Col[j].neg -= A[l][j];
if (Col[j].neg > Col[j].poz)
J[j] = 1;
else
J[j] = 0;
}
// the flag gets changed bc I flipped
flag = 1;
}
else if (linmax < colmax && (colmax != 0))
{
swap(N,M,A,c,1);
// on lines
for (int i = 0; i < N; ++i)
{
Lin[i].poz += A[i][c];
Lin[i].neg -= A[i][c];
if (Lin[i].neg > Lin[i].poz)
I[i] = 1;
else
I[i] = 0;
}
// on cols
int aux = Col[c].poz;
Col[c].poz = Col[c].neg;
Col[c].neg = aux;
J[c] = 0;
// update flag
flag = 1;
}
}
// Given that I know which flips I would do on lines and columns, which ones wouldn't I do?
// If we agree that we need the while becomes some flips "sway" the solution, which can we give up?
// algorithm
/*
while (flag)
{
flag = 0;
clearout(N,M,I,J);
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
if (A[i][j] > 0) Lin[i].poz += A[i][j];
else if (A[i][j] < 0) Lin[i].neg += (-A[i][j]);
if (Lin[i].poz < Lin[i].neg)
{
I[i] = 1;
swap(N, M, A, i, 0);
++flag;
}
}
printout(N,I,0);
for (int j = 0; j < M; ++j)
{
for (int i = 0; i < N; ++i)
if (A[i][j] > 0) Col[j].poz += A[i][j];
else if (A[i][j] < 0) Col[j].neg += (-A[i][j]);
if (Col[j].poz < Col[j].neg)
{
J[j] = 1;
swap(N, M, A, j, 1);
++flag;
}
}
printout(M,J,1);
printf("\n");
}
fclose(fp);
*/
fp = fopen("flip.out", "w");
fprintf(fp, "%d\n", sum(N,M,A));
fclose(fp);
return 0;
}
/*
The question is: could it be wrong? No, because the order of operations doesn't matter, and the only operations are those; and the sum augments with each step, and also...
But could not doing a greedy step bring to the optimal solution?
-3 4 -5
1 1 -1
-1 4 -9
could be:
3 -4 5
1 1 -1
-1 4 -9
3 -4 -5
1 1 1
-1 4 9
-3 4 5
1 1 1
-1 4 9
3 4 5
-1 1 1
1 4 9
or:
-3 4 5
1 1 1
-1 4 9
3 4 5
-1 1 1
1 4 9
No. The order can't matter; it's just multiplication with -1; if the answer gets swayed, it would eventually go back. Perhaps there is a smarter way to switch rows/columns!
Instead of doing all cols and then all rows, I could do row or column in function of a rule. A checker! Uhm, perhaps I should just fill up the I, J vectors up. After doing so I can see what happens and just flip the remaining values?
*/