01背包
hdu 2602
#include <bits/stdc++.h> using namespace std; #define N 1010 #define ll long long #define inf 0x3f3f3f3f int t; int n,V; struct Node{ int w,v; }no[N]; int dp[N]; int main() { scanf("%d",&t); while(t--){ fill(dp,dp+N,0);//初始化为0 scanf("%d%d",&n,&V); for(int i =0;i<n;i++) scanf("%d",&no[i].w); for(int i =0;i<n;i++) scanf("%d",&no[i].v); for(int i =0;i<n;i++){ for(int j =V;j>=no[i].v;j--) {//逆序,dp[小容量]也是由前面更新而来,此时更新dp[j]时,用当前的,前面一定没用过。 dp[j] = max(dp[j],dp[j-no[i].v]+no[i].w);//不一定装满 } } printf("%d\n",dp[V]); } return 0; }
多重背包
hdu 1171
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define N 300010 4 #define ll long long 5 #define inf 0x3f3f3f3f 6 int t; 7 int n,V; 8 struct Node{ 9 int w,v; 10 }no[120]; 11 int dp[N],W[5100]; 12 int k,ans,sum; 13 int main() 14 { 15 16 while(~scanf("%d",&n)&&n>0) 17 { 18 ans =0; sum =0; 19 for(int i =0;i<n;i++){ 20 scanf("%d%d",&no[i].w,&no[i].v); 21 sum+=no[i].w*no[i].v; 22 k =1; 23 while(k<no[i].v){ 24 W[ans++] = k*no[i].w; 25 no[i].v-=k; 26 k<<=1; 27 } 28 W[ans++] = no[i].v*no[i].w; 29 } 30 //多重背包转化为01背包 31 fill(dp,dp+N,0);//初始化为0 32 for(int i =0;i<ans;i++){ 33 for(int j =sum/2;j>=W[i];j--){ 34 dp[j] = max(dp[j],dp[j-W[i]]+W[i]); 35 } 36 } 37 printf("%d %d\n",sum-dp[sum/2],dp[sum/2]); 38 } 39 return 0; 40 }
完全背包
hdu 1114
#include <bits/stdc++.h> using namespace std; #define N 10110 #define ll long long #define inf 0x3f3f3f3f struct Node{ int w,v; }no[520]; int dp[N]; int t,n,m,p; int main() { scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); m-=n; scanf("%d",&p); for(int i=0;i<p;i++){ scanf("%d%d",&no[i].w,&no[i].v); } fill(dp,dp+N,inf); dp[0] = 0; //要装满 for(int i =0;i<p;i++){ for(int j =no[i].v;j<=m;j++){//完全背包 dp[j]=min(dp[j],dp[j-no[i].v]+no[i].w); } } if(dp[m]!=inf){ printf("The minimum amount of money in the piggy-bank is %d.\n",dp[m]); } else{ printf("This is impossible.\n"); } } return 0; }
恰好装满问题
是否恰好装满的解法不同只在于初始值的不同
恰好装满:
求最大值时,除了dp[0] 为0,其他都初始化为无穷小 -0x3f3f3f3f
求最小值时,除了dp[0] 为0,其他都初始化为无穷大 0x3f3f3f3f
不必恰好装满: 全初始化为0