首先比较容易想到是状态压缩DP

令$f[S]$表示选取了集合$S$以后,已经送了最少次数$cnt$且当前电梯剩下的体积$rest$最大(即$f[S]$是一个二元组$(cnt, rest)$)

于是$f[S] = min_{i \in S} f[S - {i}] + v[i]$

重载的$<$和$+$运算详情就请看程序好了,反正就是一个贪心思想,总复杂度$O(n * 2 ^ {n - 1})$

 

 1 /**************************************************************
 2     Problem: 2621
 3     User: rausen
 4     Language: C++
 5     Result: Accepted
 6     Time:532 ms
 7     Memory:13092 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <algorithm>
12  
13 using namespace std;
14 const int N = 20;
15 const int S = 1 << N;
16 const int inf = 1e9;
17  
18 int n, mx, mxs;
19 int a[S];
20  
21 struct data {
22     int cnt, rest;
23     data(int _c = 0, int _r = mx) : cnt(_c), rest(_r) {}
24      
25     inline data operator + (int t) const {
26         static data res;
27         res = *this;
28         res.rest -= t;
29         if (res.rest < 0) ++res.cnt, res.rest += mx;
30         return res;
31     }
32      
33     inline bool operator < (const data &d) const {
34         return cnt == d.cnt ? rest < d.rest : cnt < d.cnt;
35     }   
36 } f[S];
37  
38 int main() {
39     int i, s, t, now;
40     scanf("%d%d", &n, &mx);
41     mxs = (1 << n) - 1;
42     for (i = 1; i <= n; ++i) scanf("%d", &a[1 << i - 1]);
43     f[0] = data(0, mx);
44     for (s = 1; s <= mxs; ++s) {
45         t = s, f[s] = data(inf, mx);
46         while (t) {
47             now = t & (-t);
48             f[s] = min(f[s], f[s ^ now] + a[now]);
49             t -= now;
50         }
51     }
52     printf("%d\n", f[mxs].cnt + (f[mxs].rest != mx));
53     return 0;
54 }
55 
View Code

 

posted on 2015-05-01 21:29  Xs酱~  阅读(502)  评论(2编辑  收藏  举报