动态规划之01背包
来源:互联网 发布:ubuntu重启网络管理 编辑:程序博客网 时间:2024/05/18 16:38
#1038 : 01背包
- 样例输入
5 1000144 990487 436210 673567 581056 897
- 样例输出
2099
描述
且说上一周的故事里,小Hi和小Ho费劲心思终于拿到了茫茫多的奖券!而现在,终于到了小Ho领取奖励的时刻了!
小Ho现在手上有M张奖券,而奖品区有N件奖品,分别标号为1到N,其中第i件奖品需要need(i)张奖券进行兑换,同时也只能兑换一次,为了使得辛苦得到的奖券不白白浪费,小Ho给每件奖品都评了分,其中第i件奖品的评分值为value(i),表示他对这件奖品的喜好值。现在他想知道,凭借他手上的这些奖券,可以换到哪些奖品,使得这些奖品的喜好值之和能够最大。
提示一:合理抽象问题、定义状态是动态规划最关键的一步
提示二:说过了减少时间消耗,我们再来看看如何减少空间消耗
输入
每个测试点(输入文件)有且仅有一组测试数据。
每组测试数据的第一行为两个正整数N和M,表示奖品的个数,以及小Ho手中的奖券数。
接下来的n行描述每一行描述一个奖品,其中第i行为两个整数need(i)和value(i),意义如前文所述。
测试数据保证
对于100%的数据,N的值不超过500,M的值不超过10^5
对于100%的数据,need(i)不超过2*10^5, value(i)不超过10^3
输出
对于每组测试数据,输出一个整数Ans,表示小Ho可以获得的总喜好值。
题意: 经典的01背包问题, need[i]可以看成重量, value就是价值. 奖券数就是背包的容量.
分析: 用了两种方法来解决这道题,复杂度差别很大.
比较慢的方法:
#include<bitset> //900ms#include<map>#include<vector>#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<stack>#include<queue>#include<set>#define inf 0x3f3f3f3f#define mem(a,x) memset(a,x,sizeof(a))using namespace std;typedef long long ll;typedef pair<int,int> pii;inline int in(){ int res=0;char c;int f=1; while((c=getchar())<'0' || c>'9')if(c=='-')f=-1; while(c>='0' && c<='9')res=res*10+c-'0',c=getchar(); return res*f;}const int N=100010;int dp[N*5],v[5555],w[555]; //dp[i]表示 价值和 为i的时候最小的重量是多少int main(){ int n=in(),m=in(),sum=0; for(int i=0;i<n;i++) { w[i]=in(),v[i]=in(); sum += v[i]; } mem(dp,inf); //初始化为无穷大 dp[0]=0; for(int i=0;i<n;i++) { for(int j=sum;j>=v[i];j--) //从sum开始逆向循环,保证每个物品只能被用一次 { dp[j]=min(dp[j],dp[j-v[i]]+w[i]); } } for(int i=sum;i>=0;i--) { if(dp[i]<=m) { printf("%d\n",i); break; } } return 0;}
比较经典的方法:
由于hihocoder是单组数据, 不用每次给数组赋值0. 多组数据的时候要记得归零
#include<bitset> //195ms#include<map>#include<vector>#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<stack>#include<queue>#include<set>#define inf 0x3f3f3f3f#define mem(a,x) memset(a,x,sizeof(a))using namespace std;typedef long long ll;typedef pair<int,int> pii;inline int in(){ int res=0;char c;int f=1; while((c=getchar())<'0' || c>'9')if(c=='-')f=-1; while(c>='0' && c<='9')res=res*10+c-'0',c=getchar(); return res*f;}const int N=100010;int dp[N],w[555],v[555]; //重量为i的时候最大的价值是多少int main(){ int n=in(),m=in(); for(int i=0;i<n;i++) { w[i]=in(),v[i]=in(); } for(int i=0;i<n;i++) { for(int j=m;j>=w[i];j--) //从m开始逆向循环,保证每个物品只能用一次 { dp[j]=max(dp[j],dp[j-w[i]]+v[i]); } } printf("%d\n",dp[m]); return 0;}
第一种方法在这里显然是慢了很多的,但是要是w[i]与背包容量的值变得很大, 而value值变得很小, 就体现出它的优势了.比如下面这题
Accept: 15 Submit: 32
Time Limit: 3000 mSec Memory Limit : 32768 KB
Problem Description
Given a set of n items, each with a weight w[i] and a value v[i], determine a way to choose the items into a knapsack so that the total weight is less than or equal to a given limit B and the total value is as large as possible. Find the maximum total value. (Note that each item can be only chosen once).
Input
The first line contains the integer T indicating to the number of test cases.
For each test case, the first line contains the integers n and B.
Following n lines provide the information of each item.
The i-th line contains the weight w[i] and the value v[i] of the i-th item respectively.
1 <= number of test cases <= 100
1 <= n <= 500
1 <= B, w[i] <= 1000000000
1 <= v[1]+v[2]+...+v[n] <= 5000
All the inputs are integers.
Output
For each test case, output the maximum value.
Sample Input
Sample Output
题意: 依然是01背包,,,
分析:数据变了, 换一种想法就行了.
#include<bitset> //1000+ms#include<map>#include<vector>#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<stack>#include<queue>#include<set>#define inf 0x3f3f3f3f#define mem(a,x) memset(a,x,sizeof(a))using namespace std;typedef long long ll;typedef pair<int,int> pii;inline int in(){ int res=0;char c; while((c=getchar())<'0' || c>'9'); while(c>='0' && c<='9')res=res*10+c-'0',c=getchar(); return res;}const int N=100010;int dp[5001],w[505],v[505]; //dp表示 价值和 为i 的时候重量的最小值int main(){ int T=in(); while(T--) { int n=in(),m=in(); int sum=0; for(int i=0;i<n;i++) { w[i]=in(),v[i]=in(); sum += v[i]; } mem(dp,inf); //初始化为无穷大 dp[0]=0; for(int i=0;i<n;i++) { for(int j=sum;j>=v[i];j--) { dp[j]=min(dp[j],dp[j-v[i]]+w[i]); } } for(int i=sum;i>=0;i--) { if(dp[i]<=m) { printf("%d\n",i); break; } } } return 0;}
- 01背包之动态规划
- 动态规划之01背包
- 动态规划之背包01
- 动态规划之01背包
- 动态规划之01背包
- 动态规划之01背包
- 动态规划之01背包
- 动态规划之01背包
- 动态规划之01背包
- 动态规划之01背包
- 动态规划之01背包
- 动态规划之背包
- 动态规划之01背包,完全背包,多重背包
- 动态规划之01背包,完全背包,多重背包模板
- 动态规划之01背包问题
- 【初学动态规划】之01背包问题
- 动态规划之01背包问题
- 动态规划之01背包问题
- 引言(7)H:遥感历史:陆卫…
- 引言(7)G:遥感历史:Land…
- 引言(7)I:遥感历史:陆卫…
- ENVI5.x入门学习素材包分享
- (matlab)plot画图的颜色线…
- 动态规划之01背包
- 华为HG8245光猫破解之旅
- C++之对象切割
- cache coherency VS memory consistency
- Java 实现根据 IP 地址获取地理位置的代码分享
- Eclipse Che安装依赖
- iOS UITableView(五) cell的文字操作及响应事件
- day05
- System.Diagnostics.Process 执行.EXE