Cod sursa(job #944038)

Utilizator AnonymouslegionAnonymous Anonymouslegion Data 27 aprilie 2013 10:47:23
Problema Lapte Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.72 kb
#include<cstring>
#include<fstream>
#include<algorithm>
#include<bitset>

using namespace std;

ifstream in("lapte.in");
ofstream out("lapte.out");

const int knmax = 110;

int len, n, spa[105], spb[105], ansa[105], ansb[105] /*dp[105][115]*/, dad[105][115][2];
bitset<110> dp[105];

void read(){
  in >> n >> len;

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

int gx, gy;

int rowrowrow(int x, int lv){
  int q, r;
  for(int i = 0; i <= len; ++i)
    dp[i].reset();
  if(lv)
  memset(dad, 0, sizeof(dad));

  dp[0][0] = 1;
  for(int i = 1; i <= n; ++i)
    for(int j = len; j >= 0; --j)
      for(int k = knmax; k >= 0; --k)if(!dp[j][k]){
        q = x / spa[i];
        for(int l = 0; l <= q; ++l){
          r = (x - (l * spa[i])) / spb[i];
          if(r > k || l > j)
            continue;
          if(dp[j - l][k - r]){
            dp[j][k] = 1;
            if(lv){
            dad[j][k][0] = i;
            dad[j][k][1] = l;
            }
          }
          if(dp[j][k] && j >= len && k >= len){
            gx = j;
            gy = k;
            return 1;
          }
        }
      }
  return 0;
}

int ans;

void solve(){
  int left = len / 2, right = 100, 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(){
  out << ans << "\n";
  for(int i = 1; i <= n; ++i)
    out << ansa[i] << " " << ansb[i] << "\n";
}

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

  return 0;
}