Cod sursa(job #18629)

Utilizator scapryConstantin Berzan scapry Data 18 februarie 2007 12:49:53
Problema Ghiozdan Scor 50
Compilator cpp Status done
Runda preONI 2007, Runda 2, Clasele 11-12 Marime 1.38 kb
#include <stdio.h>
#include <string.h>

enum { maxn = 20001, window_size = 202, inf = 0x1F1F1F1F };

int n, g;
int ob[maxn];
int sum;

int min[window_size];
bool uses[window_size][maxn];
int now, winpos;

int main()
{
	int i, stop, ipos;
	int todo_i, todo_ipos;
	FILE *f = fopen("ghiozdan.in", "r");
	if(!f) return 1;
	
	fscanf(f, "%d%d", &n, &g);
	for(i = 0; i < n; i++)
	{
		fscanf(f, "%d", &ob[i]);
		sum += ob[i];
	}
	
	fclose(f);
	f = fopen("ghiozdan.out", "w");
	if(!f) return 1;
	
	stop = g;
	if(sum < stop) stop = sum;
	
	for(now = 1, winpos = 1;
	    now <= stop;
	    now++, winpos = (winpos + 1) % window_size)
	{
		min[winpos] = inf;
		memset(uses[winpos], 0, n);
		
		for(i = 0; i < n; i++)
		{
			if(now < ob[i]) continue; //too big an object!
			
			ipos = winpos - ob[i];
			if(ipos < 0) ipos += window_size; //from the old window
			
			if(!uses[ipos][i])
				if(min[ipos] + 1 < min[winpos])
				{
					min[winpos] = min[ipos] + 1;
					
					todo_i = i;
					todo_ipos = ipos;
				}
		}
		
		if(min[winpos] != inf)
		{
			memcpy(uses[winpos], uses[todo_ipos], n);
			uses[winpos][todo_i] = true;
		}
	}
	
	//need to do this once because now == g + 1
	do
	{
		now--;
		winpos--;
		if(winpos < 0) winpos += window_size;
	} while(min[winpos] == inf);
	
	fprintf(f, "%d %d\n", now, min[winpos]);
	for(i = 0; i < n; i++)
		if(uses[winpos][i]) fprintf(f, "%d\n", ob[i]);
	
	fclose(f);
	return 0;
}