NYOJ 860 又见01背包(01背包转移方程巧用)
2015-09-01 18:42
288 查看
又见01背包
时间限制:1000 ms | 内存限制:65535 KB难度:3
描述
有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W
的物品,求所有挑选方案中物品价值总和的最大值。
1 <= n <=100
1 <= wi <= 10^7
1 <= vi <= 100
1 <= W <= 10^9
输入多组测试数据。
每组测试数据第一行输入,n 和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和 vi。
输出满足题意的最大价值,每组测试数据占一行。
样例输入
4 5 2 3 1 2 3 4 2 2
样例输出
7
先来看看背包的容量 1 <= W <= 10^9 背包的容量的最大值为10^9。用背包问题的普通转移方程dp[i][j]=max(dp[i-1][j],dp[i-1][j-
w[i]]+v[i])内存会爆掉,且会超出题目限制的时间。这里需要换方向思考,以往总是在限定的背包容量条件下找出最大总价值,
对于背包的容量太大,而已知的最大总价值确定且数值合适。可以将问题转化为在限定最大总价值条件下找出背包最小容量。即转
移方程为dp[i][j]=min(dp[i-1][j],dp[i-1][j-v[i]]+w[i])且对于此题又有dp[i][j]<=W总重。这样就能很快的求解了。
具体代码如下:
<span style="font-size:18px;">#include<cstdio> #include<cstring> #define min(a,b)(a<b?a:b) int w[110],v[110],dp[10010]; int main() { int n,W,sum,i,j; while(scanf("%d%d",&n,&W)!=EOF) { sum=0; for(i=0;i<n;++i) { scanf("%d%d",&w[i],&v[i]); sum+=v[i]; } for(i=1;i<=sum;++i) dp[i]=999999999;//初始化必须大于10^9,这个地方导致一直wa dp[0]=0; for(i=0;i<n;++i) { for(j=sum;j>=v[i];--j) dp[j]=min(dp[j],dp[j-v[i]]+w[i]); } for(i=sum;i>=0;i--) { if(dp[i]<=W) { printf("%d\n",i); break; } } } return 0; } </span>
相关文章推荐
- hdu 3944 DP? lucas定理
- 【AngularJS】—— 12 独立作用域
- JQuery中的DOM操作
- nio文件通道
- leetcode 2: Add Two Numbers
- JAVA之编码/解码 -- 各种环境下可能会发生的乱码问题及解决方案
- Pdf格式文件怎么修改
- poj 1286 Necklace of Beads (polya(旋转+翻转)+模板)
- 周记——20150831
- 海盗分宝石
- 人月神话读后感
- EAIntroView–高度可定制的iOS应用欢迎页通用解决方案
- ORACLE索引失效原因归纳[转]
- 论char数组在c++和java中的不同
- 第二届CCF软件能力认证
- iOS js oc相互调用(JavaScriptCore)(二)
- Python - Headless Selenium WebDriver Tests using PyVirtualDisplay
- Windows下使用MongoDb的经验
- HDU 1106 排序
- 100个高质量Java开发者博客