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