Cod sursa(job #2661811)

Utilizator matthewvandyekBeatrice Lollio matthewvandyek Data 22 octombrie 2020 19:05:27
Problema Jocul Flip Scor 30
Compilator c-64 Status done
Runda Arhiva de probleme Marime 5.51 kb
#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?
*/