ZOJ 3164 Cookie Choice(终极背包)
2012-11-08 17:18
369 查看
题意:
给出N类物品,有价值,数量,价格
还有一些限制组,限制的组里面最多只能选一类物品,问D钱最多能获得的价值,并且D钱必须花完
思路:
看完背包9讲,感觉这一题还是不难理解的。首先,对于没有组的限制的X类物品,进行一遍背包(01背包、完全背包、多重背包)。
其次,对于有组的限制的物品,就需要再次考虑下了。这次要用到泛化背包和分组背包的思想。每一组只能选择组里面的一类物品。
于是试图考虑,如果我分给这个组V(range from 0 to D)的容量,能够最多拿到多少价值。因为这个组有X类物品,只能选择一类,
所以需要先对这个组的每一类物品进行一次01背包,获得分配给这类物品V的容量取得的最大价值,然后再对这个组的X类物品进行分组背包。
最后,针对上述组进行一次分组背包,问题得以解决。
(第一次开始自己尝试描述算法思路,Orz Orz,坚持坚持)
给出N类物品,有价值,数量,价格
还有一些限制组,限制的组里面最多只能选一类物品,问D钱最多能获得的价值,并且D钱必须花完
思路:
看完背包9讲,感觉这一题还是不难理解的。首先,对于没有组的限制的X类物品,进行一遍背包(01背包、完全背包、多重背包)。
其次,对于有组的限制的物品,就需要再次考虑下了。这次要用到泛化背包和分组背包的思想。每一组只能选择组里面的一类物品。
于是试图考虑,如果我分给这个组V(range from 0 to D)的容量,能够最多拿到多少价值。因为这个组有X类物品,只能选择一类,
所以需要先对这个组的每一类物品进行一次01背包,获得分配给这类物品V的容量取得的最大价值,然后再对这个组的X类物品进行分组背包。
最后,针对上述组进行一次分组背包,问题得以解决。
(第一次开始自己尝试描述算法思路,Orz Orz,坚持坚持)
#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; #define max(a,b) (((a) > (b)) ? (a) : (b)) const int MAXN = 1500; const int INF = 1e9; int Ki[MAXN], Ei[MAXN], Pi[MAXN]; int w[10][MAXN], f[MAXN]; int n, d, g; void init_input() { for (int i = 1; i <= n; ++i) scanf("%d %d %d", &Ki[i], &Ei[i], &Pi[i]); scanf("%d%*c", &g); memset(f, 0, sizeof(f)); char s[1000]; for (int i = 1; i <= g; ++i) { gets(s); int j = 0; while (j < strlen(s)) { if ('1' <= s[j] && s[j] <= '9') { int sum = 0; while ('0' <= s[j] && s[j] <= '9') sum = 10 * sum + s[j] - '0', ++j; f[sum] = i; } else ++j; } } } void init_dp(int dp[]) { fill(dp, dp + d + 1, -INF); dp[0] = 0; } void complete_pack(int w, int v, int dp[]) { for (int i = w; i <= d; ++i) if (dp[i-w] > -INF) // 必须装满的时候,是需要这么一个判断的。-INF表示没有合法解 dp[i] = max(dp[i], dp[i-w] + v); } void zero_one_pack(int w, int v, int dp[]) { for (int i = d; i >= w; --i) if (dp[i-w] > -INF) dp[i] = max(dp[i], dp[i-w] + v); } void multiple_pack(int w, int v, int n, int dp[]) { int i = 1, c = n; while (i < c) { zero_one_pack(i * w, i * v, dp); c -= i; i *= 2; } if (c) zero_one_pack(c * w, c * v, dp); } int main() { while (scanf("%d %d", &n, &d) != EOF) { init_input(); int dp[MAXN], temp[MAXN]; init_dp(dp); for (int i = 1; i <= g; ++i) init_dp(w[i]); for (int i = 1; i <= n; ++i) { if (f[i]) init_dp(temp); if (!Ki[i] || Ki[i] * Pi[i] >= d) complete_pack(Pi[i], Ei[i], f[i] ? temp : dp); else multiple_pack(Pi[i], Ei[i], Ki[i], f[i] ? temp : dp); if (f[i]) for (int j = 0; j <= d; ++j) w[f[i]][j] = max(w[f[i]][j], temp[j]); } for (int i = 1; i <= g; ++i) // w[g][d] : g个组,每个组有d个物品,每个组最多选择其中一个 for (int j = d; j >= 0; --j) for (int k = 0; k <= j; ++k) if (w[i][k] > -INF && dp[j-k] > -INF) dp[j] = max(dp[j], dp[j-k] + w[i][k]); if (dp[d] >= 0) printf("%d\n", dp[d]); else printf("i'm sorry...\n"); } return 0; }
相关文章推荐
- Zoj 3164 Cookie Choice(多重背包+分组背包,更新队列优化)
- ZOJ 3164 Cookie Choice 分组背包 混合背包
- zoj 3164 Cookie choice 解题报告
- ZOJ Cookie Choice 多重背包 单调队列优化 分组背包 泛化物品求和
- Cookie Choice II ZOJ - 3297 头尾指针维护
- zoj 3164 分组背包 + 各种背包
- zoj 3164 分组背包 + 各种背包
- zoj 3164 各种背包
- ZOJ Problem Set - 3812 牡丹江网络赛D题 状态压缩 背包
- ZOJ-3211-Dream City-DP背包问题+贪心
- ZOJ - 3956Course Selection System(背包)
- Course Selection System ZOJ - 3956 【01背包变形】 好题~
- zoj 3524 Crazy Shopping 拓扑排序+完全背包 ★★★☆
- zoj 3626 Treasure Hunt I(树形DP+分组背包)
- ZOJ 3703 Happy Programming Contest 0-1背包 DP
- zoj 2224 || poj 2063 Investment(完全背包!)
- ZOJ 3812 We Need Medicine(dp、背包、状态压缩、路径记录)
- zoj 3689 Digging 贪心+01背包
- ZOJ 3201 树形dp+背包(简单题)
- ZOJ-3623 Battle Ships (完全背包 应用题)