您的位置:首页 > 其它

BZOJ2621 [Usaco2012 Mar]Cows in a Skyscraper

2015-05-01 21:29 274 查看
首先比较容易想到是状态压缩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})$

/**************************************************************
Problem: 2621
User: rausen
Language: C++
Result: Accepted
Time:532 ms
Memory:13092 kb
****************************************************************/

#include <cstdio>
#include <algorithm>

using namespace std;
const int N = 20;
const int S = 1 << N;
const int inf = 1e9;

int n, mx, mxs;
int a[S];

struct data {
int cnt, rest;
data(int _c = 0, int _r = mx) : cnt(_c), rest(_r) {}

inline data operator + (int t) const {
static data res;
res = *this;
res.rest -= t;
if (res.rest < 0) ++res.cnt, res.rest += mx;
return res;
}

inline bool operator < (const data &d) const {
return cnt == d.cnt ? rest < d.rest : cnt < d.cnt;
}
} f[S];

int main() {
int i, s, t, now;
scanf("%d%d", &n, &mx);
mxs = (1 << n) - 1;
for (i = 1; i <= n; ++i) scanf("%d", &a[1 << i - 1]);
f[0] = data(0, mx);
for (s = 1; s <= mxs; ++s) {
t = s, f[s] = data(inf, mx);
while (t) {
now = t & (-t);
f[s] = min(f[s], f[s ^ now] + a[now]);
t -= now;
}
}
printf("%d\n", f[mxs].cnt + (f[mxs].rest != mx));
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: