Cod sursa(job #615826)

Utilizator themihhMihnea Donciu themihh Data 11 octombrie 2011 00:14:53
Problema Jocul Flip Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.3 kb
// Flip.cpp : Defines the entry point for the console application.
//


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct node
{
    int **mat;
    int n, m;
    node *next;
} Node;

typedef struct stack
{
    Node *top;
    int length;
} Stack;

Node *initNode(int **mat, int n, int m)
{
    Node *p = (Node *) malloc(sizeof(Node));
    p->mat = mat;
    p->m = m;
    p->n = n;
    p->next = NULL;
    return p;
}

Stack *initStack()
{
    Stack *s = (Stack *) malloc(sizeof(Stack));
    s->top = NULL;
    s->length = 0;
    return s;
}

void push(Stack *s, Node *p)
{
    p->next = s->top;
    s->top = p;
    s->length++;
}
        
Node *pop(Stack *s)
{
    Node *p = s->top;
    s->top = p->next;
    s->length--;
    return p;
}
        
int isEmpty(Stack *s)
{
    return (s->length == 0);
}

void print(int **a, int n, int m)
{
    int i, j;
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < m; j++)
        {
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
}

int **clone(int **a, int n, int m)
{
	int **b;
	int i, j;
	b = (int **) malloc(sizeof(int *) * n);
	for (i = 0; i < n; i++)
	{
		b[i] = (int *) malloc(sizeof(int) * m);
		for (j = 0; j < m; j++)
		{
			b[i][j] = a[i][j];
		}
	}
	return b;
}

void printStack(Stack *s)
{
    Node *p = s->top;
    int i = 0;
    while (p != NULL)
    {
        printf("Nod %d:\n", i);
        print(p->mat, p->n, p->m);
        printf("\n");
        i++;
        p = p->next;
    }
}

void comutaLinie(int **a, int i, int m)
{
    int j;
    for (j = 0; j < m; j++)
    {
        a[i][j] = -a[i][j];
    }
}

void comutaColoana(int **a, int j, int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        a[i][j] = -a[i][j];
    }
}

int linieValida(int **a, int i, int m)
{
    int j, suml = 0;
    for (j = 0; j < m; j++)
    {
        suml += a[i][j];
    }
	return (suml >= 0);
}

int coloanaValida(int **a, int j, int n)
{
    int i, sumc = 0;
    for (i = 0; i < n; i++)
    {
        sumc += a[i][j];
    }
	return (sumc >= 0);
}

int sum(Node *p)
{
    int i, j;
    int sum = 0;
    for (i = 0; i < p->n; i++)
    {
        for (j = 0; j < p->m; j++)
        {
            sum += p->mat[i][j];
        }
    }
    return sum;
}

void init(Stack *s, Node *p)
{
    push(s, p); //salvez starea curenta a matricei pe stiva
}

int amSuccesor(Stack *s, int k, int *comutat)
{
    Node *p, *q;
    int **a, **b;
    if (comutat[k] == 2)
    {
        return 0;    //am comutat deja la pasul k, deci nu mai am succesor
    }
    p = s->top;
    a = p->mat;
	b = clone(a, p->n, p->m);
	
	if (comutat[k] == 1)
	{
		//comutaLinie(b, k, p->m);
		comutaColoana(b, k, p->n);
	}
    comutat[k]++;

	q = (Node *) malloc(sizeof(Node));
	q->mat = b;
	q->m = p->m;
	q->n = p->n;
	q->next = NULL;
	push(s, q);	//salvez noul nod pe stiva pentru a fi validat
    return 1;
}

int valid(Stack *s, int k, int *comutat)
{  //calculez sumele pe coloane
    int i, j;
	int **b;
	Node *p;
	p = pop(s);
	b = p->mat;
	
	/*for (j = 0; j < p->m; j++)
	{
		if (!coloanaValida(b, j, p->n))
		{
			comutaColoana(b, j, p->n);
		}
	}*/
	for (i = 0; i < p->n; i++)
	{
		if (!linieValida(b, i, p->m))
		{
			comutaLinie(b, i, p->m);
		}
	}
	push(s, p);	//daca nodul e valid, il pun la loc pe stiva
    return 1;
}

int back(int **a, int n, int m)
{
    int as, i, k = 0, sumk, maxsum = 0;
    Stack *st;
    Node *p, *q;
    int *comutat;

    st = initStack();
    p = initNode(a, n, m);
    comutat = (int *) malloc(sizeof(int) * n);
    init(st, p);
	//printStack(st);
    comutat[0] = 0; //la primul pas nu am comutat nimic
    while (k >= 0 && k < m)
    {
        while ((as = amSuccesor(st, k, comutat)) == 1)
		{
			if (valid(st, k, comutat))
			{
				break;
			}
		}
		q = pop(st);	//nodul e scos de pe stiva
        if (as)
        {
            if ((sumk = sum(q)) > maxsum)
            {
                maxsum = sumk;
				//printf("Suma candidat: %d\n", maxsum);
				//print(q->mat, q->n, q->m);
            }
            k++;
			if (k < n)
			{
				comutat[k] = 0;
				init(st, q);	//adaug in stiva nodul pe nivelul k+1
			}
			else
			{
				k--;
			}
        }
        else
        {
            k--;
			for (i = 0; i < q->n; i++)
			{
				free(q->mat[i]);
			}
			free(q->mat);
			free(q);
        }
    }
	free(comutat);
	free(st);
	return maxsum;
}

int main(int argc, char* argv[])
{
    int **a, sum = 0;
    int n, m;
    int i, j, k;
    FILE *f1, *f2;
	//time_t t1, t2;

	//time(&t1);
    f1 = fopen("flip5.in", "r");
    f2 = fopen("flip.out", "w");

    if (f1 == NULL || f2 == NULL)
    {
        return 0;
    }

    if (fscanf(f1, "%d\n%d\n", &n, &m) < 0)
    {
        fclose(f1);
        fclose(f2);
    }
    a = (int **) malloc(sizeof(int *) * n);
    for (i = 0; i < n; i++)
    {
        a[i] = (int *) malloc(sizeof(int) * m);
        for (j = 0; j < m; j++)
        {
            k = fscanf(f1, "%d", &a[i][j]);
        }
    }

    sum = back(a, n, m);
    fprintf(f2, "%d", sum);
    fclose(f1);
    fclose(f2);
	//time(&t2);
	//printf("Timp executie: %.2lf secunde\n", difftime(t2,t1));
	return 0;
}