01背包问题总结
来源:互联网 发布:ubuntu搭建samba 编辑:程序博客网 时间:2024/04/27 21:58
总结一下 按照:http://blog.csdn.net/libin56842/article/details/9338841 这个博客 提供的题号(感谢大牛) 和自己多加的几道01背包的题目。
其状态转移方程是:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
01背包的裸代码:(节省一维空间)
for(int i=0;i<n;i++) for(int j=V;j>=weight[i];j--) dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
1.HDU2602:Bone Collector
01背包裸题
http://acm.hdu.edu.cn/showproblem.php?pid=2602
#include<cstring>#include<climits>#include<cstdio>#include<cstdlib>#include<map>#include<stack>#include<vector>#include<iostream>#include<algorithm>using namespace std;const int maxn=1010;int dp[maxn],v[maxn],w[maxn];int main(){ int T;cin>>T; while(T--){ memset(dp,0,sizeof(dp)); int n,W;cin>>n>>W; for(int i=0;i<n;i++) cin>>v[i]; for(int i=0;i<n;i++) cin>>w[i]; for(int i=0;i<n;i++) for(int j=W;j>=w[i];j--) dp[j]=max(dp[j],dp[j-w[i]]+v[i]); cout<<dp[W]<<endl; }}
2.hdu2546 :饭卡
http://acm.hdu.edu.cn/showproblem.php?pid=2546
很经典的一道01背包题,要注意的是这里只要剩余的钱不低于5元,就可以购买任何一件物品,所以5在这道题中是很特许的,再使用01背包之前,我们首先要在现在所拥有的余额中保留5元,用这五元去购买最贵的物品,而剩下的钱就是背包的总容量,可以随意使用,因此可得代码.
#include<bits/stdc++.h>using namespace std;int dp[51010],n,m,a[1010];int main(){ while(cin>>n&&n) { memset(dp,0,sizeof(dp)); memset(a,0,sizeof(a)); for(int i=0;i<n;i++) cin>>a[i]; cin>>m; if(m<5){ cout<<m<<endl; continue; } m-=5; sort(a,a+n); for(int i=0;i<n-1;i++) for(int j=m;j>=a[i];j--) dp[j]=max(dp[j],dp[j-a[i]]+a[i]); cout<<m-a[n-1]-dp[m]+5<<endl; }}
3.HDU1171:Big Event in HDU
http://acm.hdu.edu.cn/showproblem.php?pid=1171
题意:01背包的变形,给你物品和种类,分成平均两部分,两部分分之差最小。先以sum/2去选择最多质量的物品,求得结果小于等于另一半。
#include<cstring>#include<climits>#include<cstdio>#include<cstdlib>#include<map>#include<stack>#include<vector>#include<iostream>#include<algorithm>using namespace std;int dp[255010],val[5010];int main(){ int n; while(cin>>n){ memset(dp,0,sizeof(dp)); if(n<=0) break; int sum=0,t=0; for(int i=0;i<n;i++){ int a,b; cin>>a>>b; sum+=a*b; for(int j=0;j<b;j++) val[t++]=a; } for(int i=0;i<t;i++) for(int j=sum/2;j>=val[i];j--) dp[j]=max(dp[j],dp[j-val[i]]+val[i]); cout<<max(sum-dp[sum/2],dp[sum/2])<<" "<<min(sum-dp[sum/2],dp[sum/2])<<endl; }}
4.HDU2639:Bone Collector II(01背包第k优解)
http://acm.hdu.edu.cn/showproblem.php?pid=2639
题意:这题不是01背包最优解,而是第k优解
思路:这里加一维 ,每个状态下第k解,dp[n][k],打个比方,一个年级有几个班,你要知道年级第一,你就需要知道每个班第一,你要知道年级前k名,你就要知道每个班前k名,所以这里,求出每个决策k个解,在排序后转移。
#include<bits/stdc++.h>using namespace std;int dp[1010][50],value[110],cost[110],A[50],B[50];int main(){ int T;cin>>T; while(T--){ memset(dp,0,sizeof(dp)); int n,v,k; cin>>n>>v>>k; for(int i=0;i<n;i++) cin>>value[i]; for(int i=0;i<n;i++) cin>>cost[i]; for(int i=0;i<n;i++) { for(int j=v;j>=cost[i];j--) { for(int kk=0;kk<k;kk++) { A[kk]=dp[j-cost[i]][kk]+value[i]; B[kk]=dp[j][kk]; } A[k]=-1,B[k]=-1; int a=0,b=0,c=0; while(c<k&&(a<k||b<k)) { if(A[a]>B[b]) dp[j][c]=A[a],a++; else dp[j][c]=B[b],b++; if(dp[j][c]!=dp[j][c-1]) c++; } } } cout<<dp[v][k-1]<<endl; }}
5.HDU2955:Robberies
http://acm.hdu.edu.cn/showproblem.php?pid=2955
题意:这题带了点概率的知识,实质还是01背包选择问题,要求不被抓的概率小于一个范围,多个独立事件的概率等于他们的积,注意题目输入是被抓的总概率,和每个银行被抓的概率,注意取反。
定义dp[sum]抢到金额为sum不被抓的概率.
找到概率大于等于题目要求最大值。
#include<bits/stdc++.h>using namespace std;int v[110];double dp[10010],p[110];int main(){ int T;cin>>T; while(T--) { int sum=0; double P,N;cin>>P>>N; P=1-P; for(int i=0;i<N;i++) { cin>>v[i]>>p[i]; sum+=v[i]; p[i]=1-p[i]; } memset(dp,0,sizeof(dp)); dp[0]=1.0; for(int i=0;i<N;i++) for(int j=sum;j>=v[i];j--) dp[j]=max(dp[j],dp[j-v[i]]*p[i]); for(int i=sum;i>=0;i--) { if(dp[i]-P>0.00000001){ cout<<i<<endl; break; } } }}
6.HDU3466:Proud Merchants
http://acm.hdu.edu.cn/showproblem.php?pid=3466
题意:买东西,每个东西有三个特征值,p代表价格,q代表你手中钱必须不低于q才能买这个物品,v代表得到的价值。
mark:又是变种01背包,每做一个变种的,就是一种提高。。
这题因为涉及到q,所以不能直接就01背包了。因为如果一个物品是5 9,一个物品是5 6,对第一个进行背包的时候只有dp[9],dp[10],…,dp[m],再对第二个进行背包的时候,如果是普通的,应该会借用前面的dp[8],dp[7]之类的,但是现在这些值都是0,所以会导致结果出错。
于是要想到只有后面要用的值前面都可以得到,那么才不会出错。设A:p1,q1 B:p2,q2,如果先A后B,则至少需要p1+q2的容量,如果先B后A,至少需要p2+q1的容量,那么就是p1+q2 > p2+q1,变形之后就是q1-p1 < q2-p2。
#include<bits/stdc++.h>using namespace std;struct node{ int p,q,v;}a[555];int cmp(node a,node b){ return a.q-a.p<b.q-b.p;}int dp[5555];int main(){ #ifdef yxj freopen("F:\\in.txt","r",stdin); #endif // yxj int n,m; while(~scanf("%d%d",&n,&m)) { for(int i=0;i<n;i++) scanf("%d %d %d",&a[i].p,&a[i].q,&a[i].v); sort(a,a+n,cmp); memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) for(int j=m;j>=a[i].q;j--) dp[j]=max(dp[j],dp[j-a[i].p]+a[i].v); printf("%d\n",dp[m]); }}
7.HDU1864:最大报销额
http://acm.hdu.edu.cn/showproblem.php?pid=1864
题目中药注意的有几样,首先每张发票中单件物品价格不能超过600,其次发票总额不能超过1000,而且发票上的物品必须是ABC三类,将满足以上条件的发票存入数组之中,就是裸01背包
#include <fstream>#include <iostream>#include <string>#include <complex>#include <math.h>#include <set>#include <vector>#include <map>#include <queue>#include <stdio.h>#include <stack>#include <algorithm>#include <list>#include <ctime>#include <memory.h>#include <ctime>#include <assert.h>#define rep(i,a,n) for (int i=a;i<n;i++)#define per(i,a,n) for (int i=n-1;i>=a;i--)#define pb push_back#define mp make_pair#define all(x) (x).begin(),(x).end()#define fi first#define se second#define eps 1e-8#define M_PI 3.141592653589793typedef long long ll;const ll mod=1000000007;ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}using namespace std;const int N=3000010;int dp[N];int p[50];int main(){ #ifdef yxj freopen("F:\\in.txt","r",stdin); #endif // yxj double q; int n; while(cin>>q>>n&&n) { int cnt=0,Q=(int)(q*100); for(int i=0;i<n;i++) { int t,a=0,b=0,c=0,flag=0; scanf("%d",&t); for(int j=0;j<t;j++) { char C; double num; scanf(" %c:%lf",&C,&num); // cout<<c<<" "<<num<<endl; if(C=='A') a+=num*100; else if(C=='B') b+=num*100; else if(C=='C') c+=num*100; else flag=1; if(a+b+c>100000||a>60000||b>60000||c>60000) flag=1; } // cout<<a+b+c<<endl; //cout<<"flag="<<flag<<endl; if(flag) continue; else p[cnt++]=a+b+c; } // cout<<cnt<<endl; memset(dp,0,sizeof(dp)); //rep(i,0,cnt) cout<<p[i]<<endl; for(int i=0;i<cnt;i++) { for(int j=Q;j>=p[i];j--) dp[j]=max(dp[j],dp[j-p[i]]+p[i]); } printf("%.2f\n",dp[Q]/100.0); }}
8.世界。hrbust 2252
http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2252
题意:完全背包,每个勇气(背包)有花费,和勇气值(价值),每个勇气数量无限,给你一个目标勇气值,问最小的花费。就是类似告诉你 总价值,求背包最小容量。
正常求前i个背包里,花费多少得到勇气最大值。再从小往上找第一个勇气值大于等于目标值的花费,并输出,按照这个dp这里花费上界得确定找一个最大的作为上届。
还可以 定义,前i个到达勇气值j的最小值。
#include <fstream>#include <iostream>#include <string>#include <complex>#include <math.h>#include <set>#include <vector>#include <map>#include <queue>#include <stdio.h>#include <stack>#include <algorithm>#include <list>#include <ctime>#include <memory.h>#include <ctime>#include <assert.h>#define rep(i,a,n) for (int i=a;i<n;i++)#define per(i,a,n) for (int i=n-1;i>=a;i--)#define pb push_back#define mp make_pair#define all(x) (x).begin(),(x).end()#define fi first#define se second#define eps 1e-8#define M_PI 3.141592653589793typedef long long ll;const ll mod=1000000007;const int inf=99999999;ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}using namespace std;int cost[110],w[110];/*int main(){ int T;cin>>T; while(T--){ int n,m,sum=0; cin>>n>>m; for(int i=0;i<n;i++){ cin>>cost[i]>>w[i]; sum=max(sum,((m/w[i])+1)*cost[i]); } memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) for(int j=cost[i];j<=sum;j++) dp[j]=max(dp[j],dp[j-cost[i]]+w[i]); for(int i=1;i<=sum;i++) if(dp[i]>=m) { cout<<i<<endl; break; } }}*/int dp[2100];//勇气值为m的最小花费.int main(){ int T;cin>>T; while(T--){ int n,m,maxx=0;cin>>n>>m; for(int i=0;i<n;i++) cin>>cost[i]>>w[i],maxx=max(maxx,w[i]); for(int i=0;i<=m+maxx;i++) dp[i]=inf; dp[0]=0; for(int i=0;i<n;i++) for(int j=w[i];j<=m+maxx;j++) dp[j]=min(dp[j],dp[j-w[i]]+cost[i]); int res=inf; for(int i=m+maxx;i>=m;i--) { //cout<<dp[i]<<endl; res=min(res,dp[i]); } cout<<res<<endl; }}
- 01背包问题总结
- 01背包问题总结
- 01背包问题总结
- 背包(01背包、完全背包、多重背包)问题总结
- 背包问题总结(01背包、完全背包、多重背包)
- 01背包问题总结一
- 01背包问题 hnust_xiehonghao的总结
- 背包问题求解总结
- 完全背包问题总结
- 背包问题总结一
- 背包问题总结二
- 背包问题总结
- 背包问题总结
- 背包问题总结
- 背包问题总结
- 背包问题总结
- 背包问题全总结
- 背包问题总结篇
- python常见注意事项
- 免费的天气预报API接口--谷歌,雅虎,中央气象台
- Linux命令
- 如何在Ubuntu(服务器)装JDK,Tomcat,MySQL
- 详解C语言printf函数以及%占位符知识
- 01背包问题总结
- Xcode 6/7添加创建Empty Application方式
- 20 Foundation框架之NSAarry和NSMutableArray
- Fail to build seafile-server libevhtp
- 21 Foundation框架之NSSet、NSMutableSet、NSCountedSet、NSOrderedSet、NSMutableOrderedSet
- 22 Foundation框架之NSDictionary和NSMutableDictionary
- 23 Foundation框架之NSPredicate
- 24 Foundation框架之NSData和NSMutableData
- [Java]使用gzip对字符串进行压缩/解压