Cod sursa(job #164410)

Utilizator alextheroTandrau Alexandru alexthero Data 24 martie 2008 10:23:16
Problema Vanatoare Scor 55
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.58 kb
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <map>

#define inf 0x3f3f3f3f
#define abs(x) ((x) > 0 ? (x) : -(x))
#define min(i,j) ((i) > (j) ? (j) : (i))
#define pb push_back
#define nmax 20
#define cmax 66000

using namespace std;
typedef pair<int, int> ii;

int n, t, last, cate, c1, c2, p1, p2, conf1;
int c[nmax], p[nmax], prev[cmax];
int d[cmax], unde;
int a[nmax], v[nmax];
ii m[cmax];
map <int, char> M;

// hai ca nu injur in sursa..... gcd extins...

int gcd(int a, int b)
{
	if(!b) return a;
	else return gcd(b, a % b);
}

int gcm(int a, int b)
{
	return a * b / gcd(a, b);
}
ii combina(int a, int b)
{
	M.clear();
	if(m[a].first == -1) return ii(-1, -1);
	if(m[b].first == -1) return ii(-1, -1);

	c1 = m[a].first, c2 = m[b].first, p1 = m[a].second, p2 = m[b].second;
	while(c1 != c2)
	{
		if(c1 < c2) 
		{
			c1 = c2 + p1 - (c2 - c1) % p1;
			if(c2 == c1 - p1) c1 -= p1;
		}
		else
		{
			c2 = c1 + p2 - (c1 - c2) % p2;
			if(c1 == c2 - p2) c2 -= p2;
		}

		if(c1 > t || c2 > t) break;
		if(c1 == c2) break;
		if(M[abs(c1 - c2)]) break;
		M[abs(c1 - c2)] = 1;
	}

	if(c1 == c2 && c1 <= t && c2 <= t) return ii(c1, gcm(p1, p2));
	return ii(-1, -1);
}

void reconst(int x)
{
	if(d[x] == 1) printf("%d ", m[x].first);
	else
	{
		reconst(prev[x]);
		reconst(x - prev[x]);
	}
}

void back(int p, int conf)
{
	for(int i = 0; i <= v[p]; i++)
	{
		int nconf = conf;
		if(i) nconf += 1 << p;
		if(nconf >= conf1 || d[last] <= d[conf1] + d[nconf]) continue;
		if(p == n - 1) 
		{
			if(nconf != 0)
			{
				unde = conf1 ^ nconf;
				if(d[unde] > d[conf1] + d[nconf])
				{
					d[unde] = d[nconf] + d[conf1];
					prev[unde] = nconf;
				}
			}
		}
		else back(p + 1, nconf);
	}
}

void show(int p)
{
	for(int i = 0; i < n; i++)
		if(p & (1 << i)) printf("1");
		else printf("0");
	printf(" ");
}

void back(int p, int c1, int c2)
{
	if(p == n + 1) 
	{
		if(d[c1 ^ c2] > d[c1] + d[c2])
		{
			d[c1 ^ c2] = d[c1] + d[c2];
			prev[c1 ^ c2] = c1;
		}
	}
	else for(int i = 0; i <= 2; i++) back(p + 1, c1 * 2 + (i == 1), c2 * 2 + (i == 2));
}

int main()
{
	freopen("vanatoare.in", "r", stdin);
	freopen("vanatoare.out", "w", stdout);

	scanf("%d%d", &n, &t);
	for(int i = 0; i < n; i++) scanf("%d%d", &c[i], &p[i]);

	for(int i = 1; i < (1 << n); i++) 
	{
		cate = 0;
		for(int j = 0; j < n; j++) if(i & (1 << j)) last = j, cate++;

		if(cate == 1) m[i] = ii(c[last], p[last]);
		else m[i] = combina(i - (1 << last), 1 << last);
		if(m[i].first != -1) d[i] = 1;
		else d[i] = inf;
	}

	last = (1 << n) - 1;

	back(1, 0, 0);
	printf("%d\n", d[last]);
	reconst((1 << n) - 1);
	printf("\n");

	return 0;
}