Cod sursa(job #163852)

Utilizator victorsbVictor Rusu victorsb Data 23 martie 2008 11:26:11
Problema Vanatoare Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.77 kb
#include <cstdio>
#include <cstring>
#include <cstdlib>

#define Nmax 20
#define INF 2000000015
#define ll long long
#define MAX(a,b) ((a) >= (b) ? (a) : (b))
#define MIN(a,b) ((a) <= (b) ? (a) : (b))

int n, ct, mask, mask0;
ll t;
int c[Nmax], v[Nmax];
int a[1 << 16];
int b[1 << 16];
char ok[1 << 16];
char DP[1 << 16];
int last[1 << 16];
int pos[1 << 16];

void citire()
{
	int i;

	scanf("%d %lld\n", &n, &t);
	for (i = 1; i <= n; ++i)
		scanf("%d %d\n", &c[i], &v[i]);
}

void gcd(ll a, ll b, ll &x, ll &y, ll &d)
{
	if (b == 0)
	{
		d = a;
		x = 1;
		y = 0;
	}
	else
	{
		ll x0, y0;

		gcd(b, a % b, x0, y0, d);

		x = y0;
		y = x0 - a / b * y0;
	}
}

void scrie(int p)
{
	if (p == 0) return;

	printf("%d ", pos[p]);
	scrie(last[p]);
}

void back(int p)
{
    if (p == n)
	{
		if (ok[mask0] && DP[mask] > DP[mask ^ mask0] + 1)
		{
			DP[mask] = DP[mask ^ mask0] + 1;
			pos[mask] = b[mask0];
			last[mask] = mask ^ mask0;
		}

		return;
	}

    back(p + 1);
	
	mask += 1 << p;
	back(p + 1);
	
	mask0 += 1 << p;
	back(p + 1);

    mask -= 1 << p;
	mask0 -= 1 << p;
}

void solve()
{
	int i, mask;
	ll A, B, C, X, Y, D, DX, DY, step;

	for (i = 1; i <= n; ++i)
		if (c[i] <= t)
		{
			ok[1 << (i - 1)] = 1;
			a[1 << (i - 1)] = v[i];
			b[1 << (i - 1)] = c[i];
		}

	for (mask = 1; mask < 1 << n; ++mask)
		if (!ok[mask])
		{
			for (i = 1; i <= n; ++i)
				if (mask & (1 << (i - 1)))
					break;

			if (!ok[mask ^ (1 << (i - 1))]) break;

			A = a[mask ^ (1 << (i - 1))];
			B = - v[i];
			C = c[i] - b[mask ^ (1 << (i - 1))];

            if (A == 0 || B == 0)
			{
				if (A == 0 && B == 0)
				{
					if (C == 0)
					{
						ok[mask] = 1;
						a[mask] = 0;
						b[mask] = c[i];
					}
					continue;
				}
				else
				{
					if (A == 0 && C % B == 0 && C / B >= 0)
					{
						ok[mask] = 1;
						a[mask] = INF;
 						b[mask] = b[mask ^ (1 << (i - 1))];
					}
					if (B == 0 && C % A == 0 && C / A >= 0)
					{
						ok[mask] = 1;
						a[mask] = INF;
                        b[mask] = c[i];
    				}
				}

				continue;
			}

			gcd(A, B, X, Y, D);

			if (C % D != 0) continue;

			X *= C / D;
			Y *= C / D;
			DX = abs(B / D);
			DY = abs(A / D);

            if (X < 0 || Y < 0)
			{
				step = MAX(-X / DX, -Y / DY);
				X += step * DX;
				Y += step * DY;

				if (X < 0 || Y < 0)
					X += DX, Y += DY;
			}

			if (X >= DX && Y >= DY)
			{
				step = MIN(X / DX, Y / DY);
				X -= step * DX;
				Y -= step * DY;
			}

			if (c[i] + v[i] * Y <= t)
			{
				ok[mask] = 1;
 				a[mask] = MIN(INF, abs(A * B / D));
    			b[mask] = c[i] + v[i] * Y;
			}
    	}

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

    back(0);

	printf("%d\n", DP[(1 << n) - 1]);
	scrie((1 << n) - 1);
}

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

	citire();
	solve();

	return 0;
}