NYOJ 860 又見01揹包

又見01揹包


時間限制:1000 ms  |  內存限制:65535 KB

與以前的01揹包相比,只是修改了重量和揹包能承載0總重量的範圍,所提用以前的方法肯定會超時。
所以不妨換個對象,應爲各個物品的價值比較小,把DP的對象從針對與不同的重量計算最大的
價值,
改變成針對於不同的價值計算最小的重量。

dp[i][j] 代表前i個物品中挑選總價值爲j的最小值,不存在時就是一個充分大的值INF
最後找到dp[n][j] <= W 時的最大值j;


描述
    有n個重量和價值分別爲wi 和 vi 的 物品,從這些物品中選擇總重量不超過 W 
的物品,求所有挑選方案中物品價值總和的最大值。
  1 <= n <=100
  1 <= wi <= 10^7
  1 <= vi <= 100
  1 <= W <= 10^9
輸入
多組測試數據。
每組測試數據第一行輸入,n 和 W ,接下來有n行,每行輸入兩個數,代表第i個物品的wi 和 vi。
輸出
滿足題意的最大價值,每組測試數據佔一行。
樣例輸入
4 5
2 3
1 2
3 4
2 2
樣例輸出
7

#include<stdio.h>
#include<algorithm>
#include<string.h>
#define INF 0x3f3f3f3f
#define max_N 100
using namespace std;
int main()
{
    int n,s,i,j;
    int dp[max_N+1][max_N*max_N+1];
    int w[max_N+1],v[max_N+1];
    while(~scanf("%d%d",&n,&s))
    {
        memset(dp,INF,sizeof(dp));
        for(i = 0; i<n; i++)
            scanf("%d%d",&w[i],&v[i]);
        dp[0][0] = 0;         //不要忘了初始化
        for(i = 0; i<n; i++)
            for(j = 0; j<=n*max_N; j++)//計算前i個物品價值爲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 res = 0;
        for(i=n*max_N; i>=0; i--)
            if(dp[n][i]<=s)//重量爲<=W時的最大價值
            {
                res = i;
                break;
            }
        printf("%d\n",res);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章