lightoj1200 【完全背包】
2016-07-25 10:30
211 查看
题意:
有一个能放W重的袋子,然后妻子给了老公一列清单,每个item会有价格,数量,重量。
首先得满足老婆的要求,然后在可装的地方输出最大还能拿多少使得拿的东西的钱最多。
注意标题是thief,我想大家也能知道基本上出背包题的人都是心机biao啊…)逃
思路:
1.首先要满足wife的要求是不是。
2.其次再满足husband的小心思。
后面就转化成了完全背包。
一开始类似0/1背包直接那个超时转化交了一发,肯定T。。
)然后贴了一发完全背包模板就过了。。。
——然后去看了百度百科的完全背包(没错就是百度百科),摘了几句下来
完全背包与01背包的伪代码只有v的循环次序不同而已。为什么这样一改就可行呢?
因为要保证第i次循环中的状态dp[ j ]是由状态dp[ j-w[ i ] ]递推而来。
换句话说,这正是为了保证每件物品只选一次,保证在考虑“选入第i件物品”这件策略时,依据的是一个没有已经选入第i件物品的子结果dp[ j - w[ i ] ]。
比如当你在算dp[ j(>2*w[i]) ] 的时候,其实你的dp[j-w[i]]在前面已经更新了,所以采用一维数组直接可以办到,而且每次更新的复杂度是O(W),总的来说就是O(nW);
这也是最优解法吧。
不过百度百科上还有一个优化没怎么看懂。
原文:
更高效的转化方法是:把第i种物品拆成费用为c*2^k、价值为w*2^k的若干件物品,其中k满足0<=k<=log2(V/c)+1。这是二进制的思想,因为不管最优策略选几件第i种物品,总可以表示成若干个2^k件物品的和。这样把每种物品拆成O(log2(V/c))件物品,是一个很大的改进。
wonter巨:因为一个数总能分成若干个2^i相加之和啊。
也许这样可以若有所思~
code…
有一个能放W重的袋子,然后妻子给了老公一列清单,每个item会有价格,数量,重量。
首先得满足老婆的要求,然后在可装的地方输出最大还能拿多少使得拿的东西的钱最多。
注意标题是thief,我想大家也能知道基本上出背包题的人都是心机biao啊…)逃
思路:
1.首先要满足wife的要求是不是。
2.其次再满足husband的小心思。
后面就转化成了完全背包。
一开始类似0/1背包直接那个超时转化交了一发,肯定T。。
)然后贴了一发完全背包模板就过了。。。
——然后去看了百度百科的完全背包(没错就是百度百科),摘了几句下来
完全背包与01背包的伪代码只有v的循环次序不同而已。为什么这样一改就可行呢?
因为要保证第i次循环中的状态dp[ j ]是由状态dp[ j-w[ i ] ]递推而来。
换句话说,这正是为了保证每件物品只选一次,保证在考虑“选入第i件物品”这件策略时,依据的是一个没有已经选入第i件物品的子结果dp[ j - w[ i ] ]。
比如当你在算dp[ j(>2*w[i]) ] 的时候,其实你的dp[j-w[i]]在前面已经更新了,所以采用一维数组直接可以办到,而且每次更新的复杂度是O(W),总的来说就是O(nW);
这也是最优解法吧。
不过百度百科上还有一个优化没怎么看懂。
原文:
更高效的转化方法是:把第i种物品拆成费用为c*2^k、价值为w*2^k的若干件物品,其中k满足0<=k<=log2(V/c)+1。这是二进制的思想,因为不管最优策略选几件第i种物品,总可以表示成若干个2^k件物品的和。这样把每种物品拆成O(log2(V/c))件物品,是一个很大的改进。
wonter巨:因为一个数总能分成若干个2^i相加之和啊。
也许这样可以若有所思~
code…
#include<bits/stdc++.h> //#include<cstdio> //#include<math.h> //#include<string.h> //#include<algorithm> using namespace std; typedef long long LL; typedef unsigned long long ULL; const double eps=1e-5; const double pi=acos(-1.0); const int mod=1e8+7; const LL INF=0x3f3f3f3f; const int N=1e2+10; int val ,dw ; int dp[N*N]; int main() { int cas=1; int n,w; int t,x,sum; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&w); sum=0; for(int i=1;i<=n;i++) { scanf("%d%d%d",&val[i],&x,&dw[i]); sum+=x*dw[i]; } w-=sum; if(w<0){ printf("Case %d: Impossible\n",cas++); continue; } memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++){ for(int j=dw[i];j<=w;j++){ dp[j]=max(dp[j],dp[j-dw[i]]+val[i]); } } printf("Case %d: %d\n",cas++,dp[w]); } return 0; }
相关文章推荐
- 应用程序无法正常启动
- nncq---咨询回复(地方查询慢)
- window7取消文件默认打开方式的方法
- 刺客信条III:背后的技术(或下方)的动作
- mysql 最大显示宽度关系
- ios 崩溃日志收集
- Codeforces 629 C Famil Door and Brackets(dp)
- 存储引擎MyISAM与InnoDB区别
- 性能调试 systrace工具
- 《Python核心编程》第二版--第三章 Python基础
- linux 防火墙
- HTML&CSS基础学习笔记1.17-表格的头部与尾部
- hdu 1518 Square(dfs)
- sessionStorage 、localStorage 和 cookie 之间的区别
- java图片验证码生成教程详解
- 并查集详解 (转)
- 51nod 1278
- POJ3069 萨鲁曼的大军(重庆一中高2018级信息学竞赛测验3) 解题报告
- 教你如何搭建自己的FTP服务器
- Python学习笔记--2016.07.25