Cod sursa(job #175521)

Utilizator VmanDuta Vlad Vman Data 10 aprilie 2008 00:05:40
Problema Vanatoare Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 3 kb
#include <stdio.h>

#define Nmax 16
#define infinit 0x3f3f3f3f

int T,N,i;
int C[Nmax],V[Nmax];
int P[1<<Nmax],I[1<<Nmax],R[1<<Nmax];
int best[1<<Nmax],last[1<<Nmax];

void citire()
{
 freopen("vanatoare.in","r",stdin);
 scanf("%d %d",&N,&T);
 for (i=0;i<N;++i)
     scanf("%d %d",&C[i],&V[i]);     
}

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

 
long long mod(long long a, long long n) {
    return a >= 0 ?
        a % n :
        n - ((-a) % n);
}

void chineza(int t1,int t2,int who)
{
 int v1,c1,v2,c2;
 long long x1,x2,d;
 long long k1,k2,M,PP;

 //daca nu exista solutie de dinainte
 if (P[t1]==-1)
    {
     P[who]=-1;
     return;
    }
 //daca solutia e prea departe   
 if (I[t1]==-1)
    {
     if (P[t1] % V[t2] == C[t2]) { P[who]=P[t1];I[who]=-1; }
        else P[who]=-1;
     return;   
    }
    
 v1=I[t1]; c1=R[t1];
 v2=V[t2]; c2=C[t2];
 
 euclid(v1, v2, &d, &x1, &x2);
 
 k1 = (long long) x1 * (c2-c1) / d;
 k2 = (long long) x2 * (c1-c2) / d;
 //daca nu exista solutie
 if (v1*k1+c1 != v2*k2+c2) { P[who]=-1;return; }
 M = (long long) v1 / d * v2;
 
 PP=mod( (v1*k1+c1), M );
 
 if (PP<=T) 
    {
     P[who]=PP;
     //daca P+M>T solutia urmatoare va fi sau P, sau P+M*ceva care va depasi T
     if (PP+M>T) { I[who]=-1; return; }
     I[who]=M;
     R[who]=mod(PP,M);
    }
 else P[who]=-1;   
}

void getnr(int nr,int lvl)
{
 if (nr>0 && P[nr]==-1) return;
 if (lvl==N)
    {
     if (P[nr]!=-1 && best[i-nr]+1<best[i])
        {
         best[i]=best[i-nr]+1;
         last[i]=nr;
        }
     return;
    }
 if (i&(1<<lvl)) getnr(nr+(1<<lvl),lvl+1);
 getnr(nr,lvl+1);
}

void nrmin()
{
 int smax=(1<<N),j;
 //aranjaza vanatorii
 i=1;
 P[0]=-1;
 while (i<smax)
       {
        for (j=0;j<N;++j)
            if (i&(1<<j))
               {
                //daca e un singur animal
                if (i==(1<<j)) {
                                P[i]=C[j];
                                I[i]=V[j];
                                R[i]=C[j];
                               }
                //daca sunt mai multi
                       else chineza(i-(1<<j),j,i);
                if (P[i]>-1)
                  {
                   best[i]=1;
                   last[i]=i;
                  }
                break;
               }
        ++i;       
       }
 //dinamica pt minim
 i=1;
 best[0]=0;
 while (i<smax)
       {
        if (best[i]==0)
          {
           best[i]=infinit;
           getnr(0,0);
          }
        ++i;
       }      
}

int main()
{
 citire(); 
 nrmin();
 freopen("vanatoare.out","w",stdout);
 i=(1<<N)-1;
 printf("%d\n",best[i]);
 while (i)
       {
        printf("%d ",P[last[i]]);
        i=i-last[i];
       }
 fclose(stdout);      
 return 0;
}