对于普通的01背包问题,如果修改限制条件的大小,让数据范围比较大的话,比如相比较重量而言,价值的范围比较小,我们可以试着修改dp的对象,之前的dp针对不同的重量限制计算最大的价值。这次用dp针对不同的价值计算最小的重量。

定义dp[i+1][j],前i个物品中挑选出价值总和为j时总重量的最小值(不存在时就是一个充分大的数值INF)。由于前0个物品中什么都挑选不了,所以初值为:
dp[0][0]=0;
dp[0][j]=INF;

此外,前i个物品中挑选出价值总和为j时,一定有
前i-1个物品中挑选价值总和为j的部分
前i-1个物品中挑选价值总和为j-v[i]的部分,然后再选中第i个物品。

这两种方法之一,所以就能得到
dp[i+1][j]=min(dp[i][j],dp[i][j-v[i]]+w[i]);
这一递推式。最终的答案就对应于令dp[n][j]<=W的最大j。

则核心代码为:

int dp[MAX_N+1][MAX_N*MAX_V+1];///dp数组
void solve()
{
    for(int i=0; i<=MAX_N*MAX_V; i++)
        dp[0][i]=INF;
    dp[0][0]=0;
    for(int i=0; i<n; i++)
        for(int j=0; j<=MAX_N*MAX_V; j++)
        {
            if(j<v[i])
                dp[i+1][j]=dp[i][j];
            else
                dp[i+1][j]=min(dp[i][j],dp[i][j-v[i]]+w[i]);

        }
    int ans=0;
    for(int i=0; i<=MAX_N*MAX_V; i++)
        if(dp[n][i]<+W)    ans=i;
    printf("%d\n",ans);
}
posted on 2017-07-17 15:23  渡……  阅读(653)  评论(0编辑  收藏  举报