简单背包问题
G - 小明系列故事——买年货 HDU4501
三维费用背包,枚举积分,钱数和免费个数
多维费用背包要在循环体内设计比较,而不能直接在for循环语句中设置类似普通01背包的语句j>=a[i]这样的语句,因为即使有一维不能满足,不代表其他维不能满足,这样会丢弃部分情况
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<map> #include<algorithm> using namespace std; typedef long long ll; const int N=110; int f[N][N][N]; int n,v1,v2,kk; struct node { int a,b; int w; }s[N]; int main(){ while(cin>>n>>v1>>v2>>kk){ int i; for(i=1;i<=n;i++) cin>>s[i].a>>s[i].b>>s[i].w; int j,l,k; memset(f,0,sizeof f); for(i=1;i<=n;i++){ for(j=v1;j>=0;j--){ for(k=v2;k>=0;k--){ for(l=kk;l>=0;l--){ int tmp=0; if(j-s[i].a>=0) tmp=max(tmp,f[j-s[i].a][k][l]+s[i].w); if(k-s[i].b>=0) tmp=max(tmp,f[j][k-s[i].b][l]+s[i].w); if(l-1>=0) tmp=max(tmp,f[j][k][l-1]+s[i].w); f[j][k][l]=max(f[j][k][l],tmp); } } } } cout<<f[v1][v2][kk]<<endl; } }
A - 饭卡 HDU2546
进行转换后就是普通01背包,转换就是,先提出最大的价值,取m-5作为最大容量计算,算出来最大是多少,再用m-dp[m-5]-a[n]。
本题的心路历程是,我们第一眼肯定是想到最大的最后买,但是我们接下来要证明这是正确的,我相信很多人会有疑惑,为什么在dp完后再买最大的是最好的。
因为假设存在最后买的并不是最大的,设为mid,那么一定可以把mid和最大的进行交换,下面我们来举个例子
假如最大是15,mid是10,我们在m-5用掉最多40块钱,m是50,那么这种情况的解是0,假设这是答案,那么这可以转化为我们用掉35块钱,最后再买15块,答案也是0,类推其他也是一样,因为转换不会影响总和。
所以进行m-5的01背包即可
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+5; const int inf=0x3f3f3f3f; int a[N]; int f[N]; int main(){ int n; int i,j; while(cin>>n,n){ memset(f,0,sizeof f); for(i=1;i<=n;i++) cin>>a[i]; int m; cin>>m; if(m<5){ cout<<m<<endl; continue; } sort(a+1,a+n+1); int sign=a[n]; for(i=1;i<=n-1;i++){ for(j=m-5;j>=a[i];j--){ f[j]=max(f[j],f[j-a[i]]+a[i]); } } cout<<m-f[m-5]-sign<<endl; } }
D - FATE HDU - 2159
本题是完全背包的变形,只需要设计二维状态,杀怪的时候必须要从杀怪总数-1的位置转移,其他就是完全背包,我使用了滚动数组优化
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int N=110+5; const int inf=0x3f3f3f3f; int a[N]; int b[N]; int f[N][N]; int main(){ int n,m,k,s; while(cin>>n>>m>>k>>s){ int i; for(i=1;i<=k;i++) cin>>a[i]>>b[i]; int res=inf; memset(f,0,sizeof f); for(i=1;i<=k;i++){ for(int j=b[i];j<=m;j++){ for(int x=1;x<=s;x++){ f[j][x]=max(f[j][x],f[j-b[i]][x-1]+a[i]); if(f[j][x]>=n) res=min(j,res); } } } if(res!=inf) cout<<m-res<<endl; else cout<<-1<<endl; } }
没有人不辛苦,只有人不喊疼