Cod sursa(job #944831)

Utilizator AnonymouslegionAnonymous Anonymouslegion Data 29 aprilie 2013 20:24:10
Problema Lapte Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.74 kb
#include<cstring>
#include<fstream>
#include<algorithm>
#include<bitset>

using namespace std;

const int knmax = 110;

int len, n, spa[105], spb[105], ansa[105], ansb[105], dad[105][115][2];
int dp[115], vis[115];

void read(){
  ifstream in("lapte.in");
  in >> n >> len;

  for(int i = 1; i <= n; ++i)
    in >> spa[i] >> spb[i];
}

int u, gx, gy;

int rowrowrow(int x, int lv){
  register int q, r;
  ++u;
  if(lv)
    memset(dad, 0, sizeof(dad));

  memset(vis, 0, sizeof(vis));
  memset(dp, 0, sizeof(dp));

  dp[0] = 0;
  vis[0] = 1;
  for(int i = 1; i <= n; ++i)
      for(int k = len; k >= 0; --k){
        q = x / spa[i];
        for(int l = 0; l <= q; ++l){
          r = (x - (l * spa[i])) / spb[i];
          if(l > k)
            continue;
          if(vis[k - l]){
            vis[k] = 1;
            dp[k] = max(dp[k], dp[k - l] + r);
            if(lv){
              dad[k][dp[k]][0] = i;
              dad[k][dp[k]][1] = l;
            }
          }

          if(k >= len && dp[k] >= len){
            gx = k;
            gy = dp[k];
            return 1;
          }
        }
      }
  return 0;
}

int ans;

void solve(){
  int left = 1, right = 115, mid, last = -1;
  while(left <= right){
    mid = (left + right) >> 1;

    if(rowrowrow(mid, 0)){
      last = mid;
      right = mid - 1;
    }
    else
      left = mid + 1;
  }

  ans = last;
  rowrowrow(ans, 1);

  while(gx || gy){
    int p = dad[gx][gy][0], l1 = dad[gx][gy][1];
    int l2 = (ans - l1 * spa[p]) / spb[p];
    ansa[p] = l1;
    ansb[p] = l2;
    gx -= l1;
    gy -= l2;
  }
}

void write(){
  ofstream out("lapte.out");
  out << ans << "\n";
  for(int i = 1; i <= n; ++i)
    out << ansa[i] << " " << ansb[i] << "\n";
}

int main(){
  read();
  solve();
  write();

  return 0;
}