Cod sursa(job #519180)

Utilizator savimSerban Andrei Stan savim Data 4 ianuarie 2011 13:46:48
Problema Ghiozdan Scor 26
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.56 kb
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

#define MAX_N 20010
#define MAX_G 75010
#define inf 1000000000

int n, m;      
int minNr[2][MAX_G], c[2][MAX_G];
int G[MAX_N];

void work(int st, int dr, int lin) {
	memset(c, 0, sizeof(c));
	for (int i = 1; i <= m; i++)
		c[0][i] = inf;

	//folosesc greutatile G[st], G[st + 1] .. G[dr]
	int l = 0;
	for (int i = st; i <= dr; i++) {
    	l = 1 - l;
		for (int j = 1; j <= m; j++)
			c[l][j] = c[1 - l][j];

		for (int j = 1; j <= G[i]; j++) 
			for (int k = j + G[i] * ((m - j) / G[i]); k >= j; k -= G[i])
				if (k - G[i] >= 0)
					c[l][k] = min(c[l][k], c[l][k - G[i]] + 1);

		for (int j = 1; j <= m; j++)
			c[1 - l][j] = 0;
	}

	for (int i = 1; i <= m; i++) 
		minNr[lin][i] = c[l][i];
}

void solve(int st, int dr, int val) {
	if (st == dr) {
		while (val) {
        	val -= G[st];
			printf("%d\n", G[st]);
		}

    	return;
	}

	memset(minNr, 0, sizeof(minNr));
	work(st, (st + dr) / 2, 0);
	work((st + dr) / 2 + 1, dr, 1);

	int sol = inf, pos = 0;
	for (int i = 1; i <= val; i++)
		if (minNr[0][i] + minNr[1][val - i] < sol) {
        	sol = minNr[0][i] + minNr[1][val - i];
			pos = i;
		}

	solve(st, (st + dr) / 2, pos);
	solve((st + dr) / 2 + 1, dr, val - pos);
}

int main() {

	freopen("ghiozdan.in", "r", stdin);
	freopen("ghiozdan.out", "w", stdout);

	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%d", &G[i]);

	work(1, n, 0);
	for (int i = m; i > 0; i--)
		if (minNr[0][i] != inf) {
        	printf("%d %d\n", i, minNr[0][i]);
			solve(1, n, i);
			break;
		}

	return 0;
}