Cod sursa(job #66480)

Utilizator scapryConstantin Berzan scapry Data 19 iunie 2007 12:06:29
Problema Party Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.59 kb
#include <assert.h>
#include <stdio.h>
#include <string.h>

enum { maxpers = 101, maxrules = 1001 };
enum status { none = 0, must_be, must_not_be };

int pers;
int depcount[maxpers];
int depwho[maxpers][maxpers];
status dep[maxpers][maxpers];
int mustcount;
int must[maxrules][2];

int count;
status stat[maxpers];

int k;
void validate_count()
{
	int realcount = 0, i;

	for(i = 0; i < pers; i++)
	{
		assert(stat[i] == none || stat[i] == must_be || stat[i] == must_not_be);

		if(stat[i] == must_be)
			realcount++;
	}

	assert(realcount == count);
}

bool mark(int who, status what)
{
	printf("mark %d with %d\n", who, what);

	int i;
	bool ans;

	validate_count();

	assert(what == must_be || what == must_not_be);

	if(stat[who] != none && stat[who] != what)
		return false; //break some previous rule
	
	if(stat[who] == what)
		return true; //been there done that

	stat[who] = what;

	if(what == must_be)
	{
		count++;

		for(i = 0; i < depcount[who]; i++)
		{
			if(stat[ depwho[who][i] ] != none &&
			   stat[ depwho[who][i] ] != dep[who][i])
				return false;

			ans = mark(depwho[who][i], dep[who][i]);
			if(!ans)
				return false;
		}
	}
	//XXX also have negative deps?

	return true;
}

bool bkt_must()
{
	printf("bkt_must k %d, stat: ", k);
	for(int i = 0; i < pers; i++)
		printf("%d ", stat[i]);
	printf("\n");

	if(k == mustcount)
		return true;

	if(stat[ must[k][0] ] == must_be &&
	   stat[ must[k][1] ] == must_be)
		return false;

	if(stat[ must[k][0] ] == must_be ||
	   stat[ must[k][1] ] == must_be)
	{
		k++;
		if(bkt_must())
			return true;
		k--;
	}
	else //need to select one
	{
		int count_copy = count;
		status stat_copy[maxpers];
		memcpy(stat_copy, stat, sizeof(stat));

		if(mark( must[k][0], must_be ))
		{
			k++;
			if(bkt_must())
				return true;
			k--;

			count = count_copy;
			memcpy(stat, stat_copy, sizeof(stat));
		}
		
		if(mark( must[k][1], must_be ))
		{
			k++;
			if(bkt_must())
				return true;
			k--;

			count = count_copy;
			memcpy(stat, stat_copy, sizeof(stat));
		}
	}

	return false; //no luck
}

void go()
{
	int start;
	bool ans;

	for(start = 0; start < maxpers; start++)
	{
		printf("\n\nstart %d --------------------------------------------\n", start);
		count = 0;
		memset(stat, 0, sizeof(stat));

		ans = mark(start, must_be);
		assert(ans == true);

		assert(k == 0);
		ans = bkt_must();

		if(ans)
		{
			//we're done!
			return;
		}
	}

	assert(false); //no solution
}

int main()
{
	int i, rules, a, b, type;
	FILE *f = fopen("party.in", "r");
	if(!f) return 1;

	fscanf(f, "%d%d", &pers, &rules);
	for(i = 0; i < rules; i++)
	{
		int damn = fscanf(f, "%d%d%d", &a, &b, &type);
		assert(damn == 3);
		a--; b--;

		switch(type)
		{
			case 0:
				must[mustcount][0] = a;
				must[mustcount][1] = b;
				mustcount++;

				depwho[a][ depcount[a] ] = b;
				dep[a][ depcount[a] ] = must_not_be;
				depcount[a]++;

				depwho[b][ depcount[b] ] = a;
				dep[b][ depcount[b] ] = must_not_be;
				depcount[b]++;

				break;
			case 1:
				depwho[b][ depcount[b] ] = a;
				dep[b][ depcount[b] ] = must_be;
				depcount[b]++;

				break;
			case 2:
				depwho[a][ depcount[a] ] = b;
				dep[a][ depcount[a] ] = must_be;
				depcount[a]++;

				break;
			case 3:
				depwho[a][ depcount[a] ] = b;
				dep[a][ depcount[a] ] = must_not_be;
				depcount[a]++;

				depwho[b][ depcount[b] ] = a;
				dep[b][ depcount[b] ] = must_not_be;
				depcount[b]++;

				break;
			default:
				assert(false);
		}
	}

	fclose(f);
	f = fopen("party.out", "w");
	if(!f) return 1;

	go();

	fprintf(f, "%d\n", count);
	for(i = 0; i < pers; i++)
		if(stat[i] == must_be)
			fprintf(f, "%d\n", i + 1);
	fclose(f);
	return 0;
}