hdu5410 CRB and His Birthday
2015-08-21 21:13
288 查看
本题其实是经典(完全)背包问题的一个变种,只不过需要处理一下B[i]。
设dp[i]为花费i所得糖果最大值。
根据题目,共有n堆礼物,买k个第i堆礼物获得糖果A[i] * k + B[i] (k > 0),每堆礼物数不限。
我们可以把每一堆礼物中的每一个礼物单独看成一堆。那么一共有无穷堆共k组礼物。
belong[i] = i % n代表现在的第i堆糖果原来属于哪一堆。
这样理论上下面的代码可以求解:
这个应该比较直观,容易理解。
那么下面把这个循环改成两部分。
第一部分单独考虑取第一轮dp(原来每堆糖果各拿出一个)。
第二部分仍然是完全背包。
这样就可得出答案了。
代码中的第二轮循环后面注释代码也是可行的。
acm.hdu.edu.cn/showproblem.php?pid=5410
View Code
设dp[i]为花费i所得糖果最大值。
根据题目,共有n堆礼物,买k个第i堆礼物获得糖果A[i] * k + B[i] (k > 0),每堆礼物数不限。
我们可以把每一堆礼物中的每一个礼物单独看成一堆。那么一共有无穷堆共k组礼物。
belong[i] = i % n代表现在的第i堆糖果原来属于哪一堆。
这样理论上下面的代码可以求解:
int solve(){ for(int i = 0; ; i++){ int k = i % n; for(int j = m; j >= W[k]; j--){ dp[j] = max(dp[j], dp[j -W[i]] + A[k] + (i < n ? B[k] : 0)); } } return ans = dp[m]; }
这个应该比较直观,容易理解。
那么下面把这个循环改成两部分。
第一部分单独考虑取第一轮dp(原来每堆糖果各拿出一个)。
for(int i = 0; i < n; i++){ for(int j = m; j >= W[i]; j--){ dp[i] = max(dp[j], dp[j - W[i]] + A[i] + B[i]); } }
第二部分仍然是完全背包。
for(int i = 1; i <= m; i++){ for(int j = 0; j < n; j++){ if(i >= W[j]) dp[i] = max(dp[i], dp[i - W[j]] + A[j]); } }
这样就可得出答案了。
代码中的第二轮循环后面注释代码也是可行的。
acm.hdu.edu.cn/showproblem.php?pid=5410
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1e3 + 10; int dp[maxn * 2]; int w[maxn], a[maxn], b[maxn]; int n, m; void solve(){ memset(dp, 0, sizeof dp); //preprocessing:: 0-1 packing for(int i = 0; i < n; i++){ for(int j = m; j >= w[i]; j--){ dp[j] = max(dp[j], dp[j - w[i]] + a[i] + b[i]); } } //full packing for(int i = 1; i <= m; i++){ for(int j = 0; j < n; j++){ if(i >= w[j]) dp[i] = max(dp[i - w[j]] + a[j], dp[i]); } } /* for(int i = 0; i < n; i++){ for(int j = w[i]; j <= m; j++){ dp[j] = max(dp[j], dp[j - w[i]] + a[i]); } } */ printf("%d\n", dp[m]); } int main(){ //freopen("in.txt", "r", stdin); int T; scanf("%d", &T); while(T--){ scanf("%d%d", &m, &n); for(int i = 0; i < n; i++) scanf("%d%d%d", &w[i], &a[i], &b[i]); solve(); } return 0; }
View Code
相关文章推荐
- android开发之定制ViewPager滑动事件
- 博客服务器又遇到DDOS攻击
- 根据前序序列和中序序列,重建一颗树(PHP递归实现)
- 博客服务器又遇到DDOS攻击
- 九度OJ 题目1083:特殊乘法
- Codeforces Round #311 (Div. 2)-B. Pasha and Tea-水题
- 既见君子 云胡不喜
- SDWebImage使用详解及流程分析
- python正则表达式笔记
- Magnolia安装
- jsp页面onsubmit="return checklogin();"该解决方案给
- 洛谷1051 谁拿了最多奖学金 解题报告
- 通用漏洞并提交格式说明
- 2.0-apache日志切割
- 九度OJ 题目1081:递推数列
- bootstrap注意事项(七)图片
- 部分真题整理3
- “完全背包”详解及实现(包含背包具体物品的求解)
- Android,去掉页面标题栏
- PHP上传文件