揹包dp

1. 01揹包

hdoj 2602 Bone Collector

`#include <stdio.h>
int main(void)
{
    int t,n,v,c[1000],w[1000],f[1000],i,j;

    scanf("%d",&t);
    while(t--)
        {
            scanf("%d %d",&n,&v);
            for(i=0;i<n;i++)
                {
                    scanf("%d",&w[i]);
                }
            for(i=0;i<n;i++)
                {
                    scanf("%d",&c[i]);
                }
            for(i=0;i<n;i++)
                {
                    for(j=v;j>=c[i];j--)
                        {
                            f[j]=f[j]>f[j-c[i]]+w[i]?f[j]:f[j-c[i]]+w[i];
                        }
                }
            printf("%d\n",f[v]);
        }
    return 0;
}

问题分解:当前最优解,要么包含第i种物品,要么不包含第i种物品
DP[i][j]表示前i个物品,揹包容量为j的最优值。
状态转移方程为:
DP[i][j] = max(DP[i-1][j],DP[i-1][j-v[i]] + w[i])

2. 完全揹包
正着写。

3. 多重揹包

hdoj 2191 ( 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 )

#include<stdio.h>
#include<string.h>
int main()
{
    int a[100],b[100],c[100],x[100],m,n,i,j,k,t;
    scanf("%d",&t);
    while(t--)
        {
            memset(x,0,sizeof(x));
            scanf("%d%d",&m,&n);
            for(i=0;i<n;i++)
                {
                    scanf("%d%d%d",&a[i],&b[i],&c[i]);
                }
            for(i=0;i<n;i++)
                {
                    for(j=0;j<c[i];j++)
                        {
                            for(k=m;k>=a[i];k--)
                                {
                                    x[k]=x[k]>(x[k-a[i]]+b[i])?x[k]:(x[k-a[i]]+b[i]);
                                }
                        }
                }
            printf("%d\n",x[m]);
        }
    return 0;
}
点赞