Cod sursa(job #163526)

Utilizator sandyxpSanduleac Dan sandyxp Data 22 martie 2008 14:42:44
Problema Vanatoare Scor 5
Compilator cpp Status done
Runda preONI 2008, Runda Finala, Clasele 11-12 Marime 2.29 kb
#include <cstdio>
#include <algorithm>
using namespace std;

#define FIN "vanatoare.in"
#define FOUT "vanatoare.out"
#define MAXN 16

int n, t, conf=0;
struct porc { int p, v; } A[MAXN];
struct cfg { int conf, poz, porci; } C[1<<MAXN];
int rez[MAXN], vmin;

bool operator<(const cfg &A, const cfg &B) {
    return A.porci > B.porci;
}

int cmmdc(int a, int b) {
    while (a && b) {
        if (a > b) a %= b;
        else b %= a;
    }
    return a | b;
}

void euclid(int a, int b, int &d, int &x, int &y)
{
    if (b == 0) {
        d = a;
        x = 1;
        y = 0;
    } else {
        int x0, y0;
        euclid(b, a % b, d, x0, y0);
        x = y0;
        y = x0 - (a / b) * y0;
    }
}

void solve()
{
    int i, x, crt, porci;
    porc first;
    // ax+by = d
    // v1x1 + p1 = v2x2 + p2
    // v1 x1 - v2 x2 = p2 - p1
    // a.     b.       ...d...
    for (i=(1<<n)-1; i >= 1; --i) { // back
        first.p = -1;
        for (x = i, crt = porci = 0; x; x >>= 1, ++crt) {
            if (x&1) {
                porci++;
                if (first.p == -1)
                    first = A[crt];
                else {
                    int d = A[crt].p - first.p, x1, x2;
                    euclid(first.v, -A[crt].v, d, x1, x2);
                    if (d != A[crt].p - first.p) break; // nu merge
                    // v1 x1 + p1 = y
                    // first = ( y, cmmdc(v1,v2) )
                    if (first.v*x1 + first.p > t) break; // iese din tzarc
                    first = (porc) { first.v*x1 + first.p, cmmdc(first.v, A[crt].v) };
                }
            }
        }
        if (x) continue;
        //first.p = pozitia unde vor ajunge toti porcii din config i
        C[conf++] = (cfg) { i, first.p, porci };
    }

    sort(C, C+conf);
    porci = x = 0;
    for (i = 0; porci < n && i<conf; ++i) {
        if ((x & C[i].conf) == 0) {
            x |= C[i].conf, porci += C[i].porci;
            rez[vmin++] = C[i].poz;
        }
    }
    printf("%d\n%d", vmin, rez[0]);
    for (i=1; i<vmin; ++i) {
        printf(" %d", rez[i]);
    }
    printf("\n");
}

void citire()
{
    freopen(FIN, "r", stdin);
    freopen(FOUT,"w",stdout);
    scanf("%d %d", &n, &t);
    for (int i=0; i<n; ++i) {
        scanf("%d %d", &A[i].p, &A[i].v);
    }
}

int main()
{
    citire();
    solve();
    return 0;
}