Cod sursa(job #1742838)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 17 august 2016 10:40:33
Problema Ghiozdan Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.27 kb
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>

using namespace std;

#define MaxG 75000
#define MaxW 200
#define INF 0x3f3f3f3f

int freq[MaxW + 1];
pair <int, int> objects[3000];
int dp[2][MaxG + 1];
int from[2][MaxG + 1];

void Divide(const int st, const int fn, int weight, bool printAnswer = true) {
	if (weight == 0) {
		return;
	}
	if (st == fn) {
		const int object = objects[st].first / objects[st].second;
		while (weight >= object) {
			printf("%d\n", object);
			weight -= object;
		}
	} else {
		int mid = (st + fn) / 2;
		dp[0][0] = 0;
		from[0][0] = 0;
		for (int i = 1; i <= weight; i++) {
			dp[0][i] = INF;
			from[0][i] = 0;
		}
		int now = 0;
		for (int i = st; i <= fn; i++) {
			now ^= 1;
			for (int j = 0; j < objects[i].first; j++) {
				from[now][j] = from[now ^ 1][j];
				dp[now][j] = dp[now ^ 1][j];
			}
			for (int j = objects[i].first; j <= weight; j++) {
				if (dp[now ^ 1][j] > dp[now ^ 1][j - objects[i].first] + objects[i].second) {
					dp[now][j] = dp[now ^ 1][j - objects[i].first] + objects[i].second;
					if (i <= mid) {
						from[now][j] = j;
					} else {
						from[now][j] = from[now ^ 1][j - objects[i].first];
					}
				} else {
					dp[now][j] = dp[now ^ 1][j];
					from[now][j] = from[now ^ 1][j];
				}
			}
		}
		int best = weight;
		while (dp[now][best] == INF) {
			best--;
		}
		if (printAnswer) {
			printf("%d %d\n", best, dp[now][best]);
		}
		const int divideWeight = from[now][best];
		Divide(st, mid, divideWeight, false);
		Divide(mid + 1, fn, best - divideWeight, false);
	}
}

int main() {
	freopen("ghiozdan.in", "r", stdin);
	freopen("ghiozdan.out", "w", stdout);
	
	int N, G;
	scanf("%d %d", &N, &G);
	for (int i = 0; i < N; i++) {
		int weight;
		scanf("%d", &weight);
		assert(weight <= MaxW);
		freq[weight]++;
	}
	
	int objectIndex = 0;
	for (int i = 1; i <= MaxW; i++) {
		int take = 1;
		int remaining = freq[i];
		while (remaining >= take && i * take <= G) {
			objects[objectIndex++] = make_pair(i * take, take);
			remaining -= take;
			take = take * 2;
		}
		if (remaining > 0 && i * remaining <= G) {
			objects[objectIndex++] = make_pair(i * remaining, remaining);
		}
	}
	
	Divide(0, objectIndex - 1, G);
	return 0;
}