Cod sursa(job #18841)

Utilizator ProstuStefan-Alexandru Filip Prostu Data 18 februarie 2007 14:18:43
Problema Ghiozdan Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.57 kb
#include <cstdio>
#include <functional>
#include <algorithm>

using namespace std;

const int NMAX = 1 << 15;
const int GMAX = 4096;
const unsigned VVU = 1 << 16;
const int VMAX = 1 << 17;

int N, G;
int A[NMAX];
int V[VMAX], B[VMAX];
unsigned C[GMAX];
int sol[NMAX], NS;

void read() {
	FILE *fin = fopen("ghiozdan.in", "rt");
	int i;

	fscanf(fin, " %d %d", &N, &G);

	for (i = 0; i < N; ++i)
		fscanf(fin, " %d", A + i);
	
	sort(A, A + N, greater<int>());

	fclose(fin);
}

void init() {
	int i;

	for (i = 0; i < 17; ++i)
		B[1 << i] = i;
}

void makeone(unsigned k, int poz, int v) {
	int l, ad;
	unsigned p;
	
	while (k) {
		p = (k ^ (k - 1)) & k;
		ad = p <= VVU ? 0 : 16;
		l = B[p <= VVU ? p : p >> 16u];
		V[ad + l + poz] = v;
		k -= p;
	}

}

void knapsack() {
	int i, j, k, stop;
	unsigned r, aux, c;

	memset(V, 0xff, sizeof(V));
	C[0] = 1;
	stop = (G >> 5) + 1;

	for (i = 0; i < N; ++i) {
		j = A[i] >> 5; r = A[i] & 31;

		++j;
		for (k = stop, j += k; k >= 0; --k) {
			c = C[k];

			if (r) {
				aux = C[j];
				C[j] |= c >> (32 - r);
				makeone(aux ^ C[j], j << 5, i);
			}

			--j;
			aux = C[j];
			C[j] |= c << r;
			makeone(aux ^ C[j], j << 5, i);
		}
	}
}

void recurse(int k) {
	if (k <= 0) 
		return;
	sol[NS++] = A[V[k]];
	recurse(k - A[V[k]]);
}

void write() {
	FILE *fout = fopen("ghiozdan.out", "wt");
	int i;
	
	for (i = G; i > 0 && (C[i >> 5] & (1 << (i & 31))) == 0; --i);

	recurse(i);

	fprintf(fout, "%d %d\n", i, NS);

	for (i = 0; i < NS; ++i)
		fprintf(fout, "%d\n", sol[i]);

	fclose(fout);
}

int main() {

	read();

	init();

	knapsack();

	write();

	return 0;
}