Cod sursa(job #1739654)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 9 august 2016 22:31:30
Problema Ghiozdan Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.46 kb
#include <cstdio>
#include <cstring>
#include <algorithm>
 
using namespace std;
 
#define MaxG 75000
#define MaxW 200
#define INF 0x3f3f3f3f
 
int freq[MaxW + 1];
pair <int, int> objects[3000];
int dp[2][MaxG + 1];
int from[2][MaxG + 1];
 
void Divide(const int st, const int fn, int weight, bool printAnswer = true) {
   if (weight <= 0) {
      return;
   }
   if (st == fn) {
      const int object = objects[st].first / objects[st].second;
      while (weight >= object) {
         printf("%d\n", object);
         weight -= object;
      }
   } else {
      int mid = (st + fn) / 2;
      dp[0][0] = 0;
      from[0][0] = 0;
      for (int i = 1; i <= weight; i++) {
         dp[0][i] = INF;
         from[0][i] = 0;
      }
      int now = 0;
      for (int i = st; i <= fn; i++) {
         now ^= 1;
         for (int j = 0; j < objects[i].first; j++) {
            from[now][j] = from[now ^ 1][j];
            dp[now][j] = dp[now ^ 1][j];
         }
         for (int j = objects[i].first; j <= weight; j++) {
            if (dp[now ^ 1][j] > dp[now ^ 1][j - objects[i].first] + objects[i].second) {
               dp[now][j] = dp[now ^ 1][j - objects[i].first] + objects[i].second;
               if (i <= mid) {
                  from[now][j] = j;
               } else {
                  from[now][j] = from[now ^ 1][j - objects[i].first];
               }
            } else {
               dp[now][j] = dp[now ^ 1][j];
               from[now][j] = from[now ^ 1][j];
            }
         }
      }
      int best = weight;
      while (dp[now][best] == INF) {
         best--;
      }
      if (printAnswer) {
         printf("%d %d\n", best, dp[now][best]);
      }
      const int divideWeight = from[now][best];
      Divide(st, mid, divideWeight, false);
      Divide(mid + 1, fn, best - divideWeight, false);
   }
}
 
int main() {
   freopen("ghiozdan.in", "r", stdin);
   freopen("ghiozdan.out", "w", stdout);
 
   int N, G;
   scanf("%d %d", &N, &G);
   for (int i = 0; i < N; i++) {
      int weight;
      scanf("%d", &weight);
      freq[weight]++;
   }
 
   int objectIndex = 0;
   for (int i = 1; i <= MaxW; i++) {
      int take = 1;
      int remaining = freq[i];
      while (remaining >= take) {
         objects[objectIndex++] = make_pair(i * take, take);
         remaining -= take;
         take = take * 2;
      }
      if (remaining > 0) {
         objects[objectIndex++] = make_pair(i * remaining, remaining);
      }
   }
 
   Divide(0, objectIndex - 1, G);
 
   return 0;
}