Cod sursa(job #155708)

Utilizator filipbFilip Cristian Buruiana filipb Data 12 martie 2008 09:20:05
Problema Vanatoare Scor Ascuns
Compilator cpp Status done
Runda Marime 2.25 kb
#include <stdio.h>
#include <algorithm>

using namespace std;

int N, T, c[32], v[32], bst;
int config, opt[1<<20], st[32], SOL[32];
int prev[1<<20], w[1<<20];

int bit(int X, int nr_bit)
{ return (X & (1<<nr_bit)) != 0; }

int gcd(int a, int b)
{ return (b == 0 ? a : gcd(b, a%b)); }

void gcd_extins(int a, int b, int &X, int &Y)
{
    int xp, yp;

    if (b == 0)
        X = 1, Y = 0;
    else
    {
        gcd_extins(b, a%b, xp, yp);
        X = yp; Y = xp - (a/b) * yp;
    }
}

int A, B, X, Y, D;
void back(int nivel, int new_conf, int cmmmc, int TIMP)
{
    if (TIMP > T)
        return ;
        
    if (nivel == N)
    {
        if (1 + opt[config-new_conf] < opt[config])
            opt[config] = 1 + opt[config-new_conf],
            prev[config] = config-new_conf,
            w[config] = TIMP;
        return ;
    }

    st[nivel] = 0; back(nivel+1, new_conf, cmmmc, TIMP);
    if (bit(config, nivel))
    {
        st[nivel] = 1;
        if (!cmmmc)
            back(nivel+1, new_conf + (1<<nivel), v[nivel], c[nivel]);
        else
        {
            A = cmmmc % v[nivel]; B = c[nivel] - TIMP % v[nivel];
            if (B < 0) B += v[nivel];

            D = gcd(A, v[nivel]);
            if (B % D) return ;
            gcd_extins(A, v[nivel], X, Y);
            X = (X * (B/D)) % v[nivel];
            if (X < 0) X += v[nivel];
            // X este o solutie. Solutiile sunt de forma X + i * (v[nivel]/D)
            X %= (v[nivel]/D); // aceasta este solutia minima

            back(nivel+1, new_conf + (1<<nivel), cmmmc*(v[nivel]/gcd(cmmmc, v[nivel])), TIMP + X * cmmmc);
        }

    }
    
}

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

    scanf("%d %d", &N, &T);
    for (i = 0; i < N; ++i)
        scanf("%d %d", &c[i], &v[i]);
    
    for (config = 1; config < (1<<N); ++config)
    {
        opt[config] = 9999;
        back(0, 0, 0, 0);
    }

    printf("%d\n", opt[(1<<N)-1]);
    for (i = (1<<N)-1; i; i = prev[i])
        SOL[++bst] = w[i];

    sort(SOL+1, SOL+bst+1);

    for (i = 1; i < bst; ++i)
        printf("%d ", SOL[i]);
    printf("%d\n", SOL[bst]);
    
    return 0;
}