Cod sursa(job #19134)

Utilizator bogdan2412Bogdan-Cristian Tataroiu bogdan2412 Data 18 februarie 2007 19:50:15
Problema Ghiozdan Scor 70
Compilator c Status done
Runda Arhiva de probleme Marime 2.19 kb
#include <stdio.h>
#include <string.h>

#define MAX 200
#define MAXG 75005

#define BUC 14
#define NRBUC 14
#define REST 4

int N, G;
int c[MAX + 1];

int best[NRBUC + 1][MAXG], up[NRBUC + 1][MAXG];

int bestm[BUC + 1][MAXG], upm[BUC + 1][MAXG];

int d[MAXG], p[MAXG], dl, dr;

void initdeque() { dl = 0; dr = -1; }

void adddeque(int val, int poz, int L)
{
	while ( dr >= dl && d[dr] + poz - p[dr] >= val ) dr--;
	d[++dr] = val;
	p[dr] = poz;
	if (poz - p[dl] > L)
		dl++;
}

void calculateline( int nxt[], int up[], int prv[], int cur )
{
	int i, r;
	//nxt[i] = max( prv[i - x * cur] + x | x <= c[cur] && x <= i / cur )
	//deque for every different remainder
	for (r = 0; r < cur; r++)
	{
		initdeque();
		for (i = r; i <= G; i += cur)
		{
			adddeque( prv[i], i / cur, c[cur] );
			nxt[i] = d[dl] + i / cur - p[dl];
			up[i] = i / cur - p[dl];
		}
	}
}

void getlines( int l, int r, int first[], int firstup[] )
{
	int i;
	memcpy( bestm[0], first, sizeof( bestm[0] ) );
	memcpy( upm[0], firstup, sizeof( upm[0] ) );
	for (l++, i = 1; l <= r; l++, i++)
		calculateline( bestm[i], upm[i], bestm[i - 1], l );
}

int main()
{
	freopen("ghiozdan.in", "rt", stdin);
	freopen("ghiozdan.out", "wt", stdout);

	int i, j;
	for (scanf("%d %d", &N, &G), i = 0; i < N; i++)
	{
		scanf("%d", &j);
		c[j]++;
	}

	memset(bestm[0], 0x3f, sizeof(bestm[0]));
	bestm[0][0] = 0;

	for (i = 1; i <= MAX; i++)
	{
		calculateline( bestm[i & 1], upm[i & 1], bestm[!(i & 1)], i );
		if (i % BUC == REST)
		{
			int poz = (i - REST) / BUC;
			memcpy( best[poz], bestm[i & 1], sizeof( best[poz] ) );
			memcpy( up[poz], upm[i & 1], sizeof( up[poz] ) );
		}
	}

	int poz = NRBUC, S;

	for (S = G; S >= 0 && best[poz][S] == 0x3f3f3f3f; S--);
	printf("%d %d\n", S, best[poz][S]);

	for (; poz >= 0; poz--)
	{
		i = poz * BUC + REST;
		if (poz == 0)
		{
			int tmp1[MAXG], tmp2[MAXG];
			memset(tmp1, 0x3f, sizeof(tmp1)); tmp1[0] = 0;
			memset(tmp2, 0, sizeof(tmp2));

			getlines( 0, i, tmp1, tmp2 );
		}
		else
			getlines( i - BUC, i, best[poz - 1], up[poz - 1] );

		if (poz == 0)
			j = REST;
		else
			j = BUC;
		for (; j >= 0 && i >= 0; j--, i--)
		{
			int k;
			for (k = 0; k < upm[j][S]; k++)
				printf("%d\n", i);
			S -= i * upm[j][S];
		}
	}

	return 0;
}