Advertisement
Guest User

Pakowanie

a guest
May 15th, 2014
221
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.37 KB | None | 0 0
  1. #include <vector>
  2. #include <list>
  3. #include <map>
  4. #include <set>
  5. #include <unordered_map>
  6. #include <unordered_set>
  7. #include <deque>
  8. #include <stack>
  9. #include <bitset>
  10. #include <algorithm>
  11. #include <functional>
  12. #include <numeric>
  13. #include <utility>
  14. #include <sstream>
  15. #include <iomanip>
  16. #include <cstdio>
  17. #include <cmath>
  18. #include <cstdlib>
  19. #include <ctime>
  20. #include <iostream>
  21. #include <string>
  22.  
  23. #define FOR(i,a,b)  for(int i=(a);i<(b);++i)
  24. #define FORD(i,a,b) for(int i=(a);i>=(b);--i)
  25. #define REP(i,a)    FOR(i,0,a)
  26. #define MP          make_pair
  27. #define PB          push_back
  28. #define ST          first
  29. #define ND          second
  30.  
  31. using namespace std;
  32.  
  33. typedef vector<int>             VI;
  34. typedef vector<VI>              VVI;
  35. typedef pair<int, int>          PII;
  36. typedef vector<PII>             VII;
  37. typedef long long int           LL;
  38. typedef unsigned long long int  ULL;
  39.  
  40.  
  41. const int MAXN = 26;
  42. const int MAXM = 105;
  43. const int INF = 1000000000;
  44.  
  45. int n, m;
  46.  
  47. VI objects;
  48. VI bags;
  49. LL bags_sums[MAXM];
  50.  
  51. LL obj_sum, bags_sum;
  52. LL waste[MAXN];
  53. LL maxWaste;
  54. int minBagIdx;
  55.  
  56. PII all_set[(1<<24) + 5];
  57. int all_set_size;
  58. VII sets[MAXN];
  59. int max_set_idx[MAXN];
  60.  
  61. void init_sets() {
  62.     all_set_size = 0;
  63.     FOR (i, 0, n) {
  64.         int tmp_num = all_set_size;
  65.         REP (j, tmp_num) {
  66.             if (objects[i] + all_set[j].ST <= bags.back()) {
  67.                 all_set[all_set_size] = {objects[i] + all_set[j].ST, all_set[j].ND | (1 << i)};
  68.                 ++all_set_size;
  69.             }
  70.         }
  71.         all_set[all_set_size] = {objects[i], 1 << i};
  72.         ++all_set_size;
  73.     }
  74.     sort(all_set, all_set + all_set_size);
  75.  
  76.     int idx = all_set_size-1;
  77.     FORD (i, m-1, 0) {
  78.         while (idx > 0 && all_set[idx].ST > bags[i]) {
  79.             --idx;
  80.         }
  81.         max_set_idx[i] = idx;
  82.     }
  83. }
  84.  
  85. void init_set(int bagIdx) {
  86.     FORD (i, max_set_idx[bagIdx], 0) {
  87.         bool add = true;
  88.         auto elem = all_set[i];
  89.         for (auto x : sets[bagIdx]) {
  90.             if ((elem.ND & x.ND) == elem.ND) {
  91.                 add = false;
  92.                 break;
  93.             }
  94.         }
  95.  
  96.         if (add) {
  97.             sets[bagIdx].PB(elem);
  98.         }
  99.     }
  100. }
  101.  
  102. int lower[1<<12], higher[1<<12];
  103. const int LOW_MASK = (1<<12) - 1;
  104.  
  105. inline int weight(int mask) {
  106.     return lower[mask & LOW_MASK] + higher[(mask >> 12) & LOW_MASK];
  107. }
  108.  
  109. void init_weights() {
  110.     REP (i, min(12, n)) {
  111.         REP (j, 1<<12) {
  112.             if (j & (1<<i)) {
  113.                 lower[j] = min(INF, lower[j] + objects[i]);
  114.             }
  115.         }
  116.     }
  117.     REP (i, min(12, n-12)) {
  118.         REP (j, 1<<12) {
  119.             if (j & (1<<i)) {
  120.                higher[j] = min(INF, higher[j] + objects[i+12]);
  121.             }
  122.         }
  123.     }
  124. }
  125.  
  126.  
  127. PII dfs_tmp[MAXN][1<<16], dfs_filtered[MAXN][1<<16];
  128. int dfs_filtered_size[MAXN];
  129. bool dfs_add;
  130.  
  131. inline bool cmp(PII a, PII b) {
  132.     if (__builtin_popcount(a.ND) == __builtin_popcount(b.ND)) {
  133.         return a.ST > b.ST;
  134.     }
  135.     else {
  136.         return (__builtin_popcount(a.ND) < __builtin_popcount(b.ND));
  137.     }
  138. }
  139.  
  140. const int THROW_DEPTH = 7;
  141. const int CALL_LIMIT = 1500000;
  142. int calls;
  143.  
  144. bool no_exception;
  145.  
  146. void DFS(int bagIdx, int notPacked) {
  147.     ++calls;
  148.     if (no_exception && bagIdx - minBagIdx == THROW_DEPTH) {
  149.         if (calls > CALL_LIMIT) {
  150.             throw 1;
  151.         }
  152.     }
  153.  
  154.     REP (i, int(sets[bagIdx].size())) {
  155.         dfs_tmp[bagIdx][i] = {weight(sets[bagIdx][i].ND & notPacked), sets[bagIdx][i].ND & notPacked};
  156.     }
  157.     sort(dfs_tmp[bagIdx], dfs_tmp[bagIdx] + sets[bagIdx].size());
  158.  
  159.     dfs_filtered_size[bagIdx] = 0;
  160.     FORD (i, sets[bagIdx].size()-1, 0) {
  161.         dfs_add = true;
  162.         auto new_x = dfs_tmp[bagIdx][i];
  163.         REP (j, dfs_filtered_size[bagIdx]) {
  164.             auto old_x = dfs_filtered[bagIdx][j];
  165.             if ((new_x.ND & old_x.ND) == new_x.ND
  166.                     || ((__builtin_popcount(old_x.ND) == __builtin_popcount(new_x.ND)) && (__builtin_popcount(new_x.ND ^ old_x.ND) == 2))) {
  167.                 dfs_add = false;
  168.                 break;
  169.             }
  170.         }
  171.         if (dfs_add) {
  172.             dfs_filtered[bagIdx][dfs_filtered_size[bagIdx]] = dfs_tmp[bagIdx][i];
  173.             ++dfs_filtered_size[bagIdx];
  174.         }
  175.     }
  176.  
  177.     sort(dfs_filtered[bagIdx], dfs_filtered[bagIdx]+dfs_filtered_size[bagIdx], cmp);
  178.  
  179.     REP (i, dfs_filtered_size[bagIdx]) {
  180.         auto x = dfs_filtered[bagIdx][i];
  181.         if (waste[bagIdx] + bags[bagIdx] - x.ST > maxWaste) {
  182.             continue;
  183.         }
  184.  
  185.         if (bagIdx == m - 1) {
  186.             if ((notPacked ^ x.ND) == 0) {
  187.                 printf("%d\n", m-minBagIdx);
  188.                 exit(0);
  189.             }
  190.         }
  191.         else {
  192.             waste[bagIdx + 1] = waste[bagIdx] + bags[bagIdx] - x.ST;
  193.             DFS(bagIdx + 1, notPacked ^ x.ND);
  194.         }
  195.     }
  196. }
  197.  
  198.  
  199. int main() {
  200.     scanf("%d %d", &n, &m);
  201.  
  202.     int tmp;
  203.     int max_obj = 0;
  204.     REP (i, n) {
  205.         scanf("%d", &tmp);
  206.         objects.PB(tmp);
  207.         obj_sum += objects[i];
  208.         max_obj = max(max_obj, objects[i]);
  209.     }
  210.     sort(objects.begin(), objects.end());
  211.  
  212.     int max_bag = 0;
  213.     REP (i, m) {
  214.         scanf("%d", &tmp);
  215.         // if some object can fit in bag
  216.         if (tmp >= objects[0]) {
  217.             bags.PB(tmp);
  218.             bags_sum += bags.back();
  219.             max_bag = max(max_bag, bags.back());
  220.         }
  221.     }
  222.     m = bags.size();
  223.     sort(bags.begin(), bags.end());
  224.  
  225.     // no solution
  226.     if (m == 0 || obj_sum > bags_sum || max_obj > max_bag) {
  227.         printf("NIE\n");
  228.         return 0;
  229.     }
  230.  
  231.     // too many bags
  232.     if (m > n) {
  233.         VI tmpVec = bags;
  234.         bags.clear();
  235.         FOR (i, m-n, m) {
  236.             bags.PB(tmpVec[i]);
  237.         }
  238.         m = bags.size();
  239.     }
  240.  
  241.     // init bag_sums
  242.     bags_sums[m-1] = bags[m-1];
  243.     FORD (i, m-1, 1) {
  244.         bags_sums[i-1] = bags_sums[i] + bags[i-1];
  245.     }
  246.  
  247.     init_sets();
  248.     init_weights();
  249.  
  250.     no_exception = true;
  251.     FORD (i, m-1, 0) {
  252.         init_set(i);
  253.         waste[i] = 0;
  254.         maxWaste = bags_sums[i] - obj_sum;
  255.         if (maxWaste < 0) {
  256.             continue;
  257.         }
  258.         minBagIdx = i;
  259.         try {
  260.             calls = 0;
  261.             DFS(minBagIdx, (1 << n) - 1);
  262.         }
  263.         catch (...) {
  264.             no_exception = false;
  265.         }
  266.     }
  267.  
  268.     printf("NIE\n");
  269.  
  270.     return 0;
  271. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement