Cod sursa(job #204340)

Utilizator mgntMarius B mgnt Data 22 august 2008 23:38:51
Problema Lapte Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.09 kb
/*
 * 1<=N<=100
 * 1<=L<=100
 * 1<=T<=100
 * t[k,u,x] = min{max{t[k-1,u-p,x-s], p*a[k]+s*b[k]}|0<=p<=u,0<=s<=x}
 */
#include <algorithm>
#include <fstream>
using namespace std ;
int const zero = 0 ;
int const unu  = 1 ;
int const doi  = 2 ;

int const maxn = 100 ;
// maxn - numarul maxim de persoane
int const maxl = 100 ;
// maxl - cantitatea maxima de lapte de tip A,
//        cantitatea maxima de lapte de tip B
// int const maxt = 100 ;
// maxl - maximul ce poate fi timpul minim pe
//        instanta cea mai 'lunga' a problemei
int a [maxn], b [maxn], t [maxn][unu+maxl][unu+maxl] , sola[maxn], solb [maxn];
// a[k-unu] - timpul necesar persoanei k pentru a consuma o unitate de lapte de tip A
// b[k-unu] - timpul necesar persoanei k pentru a consuma o unitate de lapte de tip B
// t[k-unu][u][x] - timpul minim in care alocand in mod optim persoanele unu,...,k
//                  se beau u unitati din laptele de tip A si x unitati din laptele
//                  de tip B
// sola[k-unu] - numarul de unitati de lapte de tip A baute de persoana k intr-o alocare optima
// solb[k-unu] - numarul de unitati de lapte de tip B baute de persoana k intr-o alocare optima

#define lin(k,p,s) (p)*a[k]+(s)*b[k]
#define val(k,u,x,p,s) t[(k)-unu][(u)-(p)][(x)-(s)]
#define fun(k,u,x,p,s) max(val(k,u,x,p,s),lin(k,p,s))
#define mn1(a,b) ((zero>(a))||((a)>(b)))?(b):(a);

int
main ( ) {
  ifstream oStreamIn  ( "lapte.in"  ) ;
  ofstream oStreamOut ( "lapte.out" ) ;
  int nper , nla , k , u , x , p , s , lo , hi , auxUnu, auxDoi , auxTrei ;
  oStreamIn >> nper >> nla ;
  for ( u = zero ; u < nper ; ++ u ) {
    oStreamIn >> a [u] ;
    oStreamIn >> b [u] ;
  }
  for ( u = zero ; u <= nla ; ++ u ) {
    for ( x = zero ; x <= nla ; ++ x ) {
      t[zero][u][x] = u * a[zero] + x * b [zero] ;
    }
  }
  // O(N^4 logN)
  for ( k = unu ; k < nper ; ++ k ) {
    for ( u = zero ; nla >= u ; ++ u ) {
      for ( x = zero ; nla >= x ; ++ x ) {
        auxUnu = - unu ;
        for ( p = zero ; u >= p ; ++ p ) {
          lo = 0 , hi = x ;
          while ( hi > unu+lo ) {
            s = (hi + lo) / doi ;
            auxDoi  = val(k,u,x,p,s);
            auxTrei = lin(k,p,s);
            if ( auxDoi <= auxTrei ) {
              hi = s ;
            } else {
              lo = s ;
            }
          }
          if ( hi == lo ) {
            auxDoi = fun(k,u,x,p,hi) ;
          } else {
            auxDoi = fun(k,u,x,p,hi);
            auxTrei =fun(k,u,x,p,lo);
            auxDoi = min(auxDoi,auxTrei) ;
          }
          auxUnu = mn1(auxUnu, auxDoi);
        }
        t[k][u][x] = auxUnu ;
      }
    }
  }
  u = nla , x = nla , k = nper - unu ;
  while ( zero < k ) {
    p = u, s = x , auxUnu = t[k][u][x];
    while ( fun(k,u,x,p,s) != auxUnu ) {
      if (zero == s) { -- p ; s = x ; } else { -- s ; }
    }
    sola[k]=p, solb[k]=s, u-=p, x-=s, --k;
  }
  sola[zero]=u, solb[zero]=x;
  oStreamOut << t[nper-unu][nla][nla] << endl ;
  for ( u = zero ; nper > u ; ++ u ) {
    oStreamOut << sola[u] << ' ' << solb[u] << endl ;
  }
  return 0 ;
}