1. 程式人生 > >1085] 揹包問題(動態規劃)

1085] 揹包問題(動態規劃)

Problem Description

在N件物品取出若干件放在容量為W的揹包裡,每件物品的體積為W1,W2……Wn(Wi為整數),與之相對應的價值為P1,P2……Pn(Pi為整數)。求揹包能夠容納的最大價值。

Input

第1行,2個整數,N和W中間用空格隔開。N為物品的數量,W為揹包的容量。(1 <= N <= 100,1 <= W <= 10000)

第2 - N + 1行,每行2個整數,Wi和Pi,分別是物品的體積和物品的價值。(1 <= Wi, Pi <= 10000)

Output

輸出可以容納的最大價值。

Input

3 6
2 5
3 8
4 9

Output

14

題解:

dp[i][j]:第i個物品前能裝入容量為j的揹包中的物品的最大價值

兩層for迴圈,i從1~N,j從1~W 

當j>=v[i]即揹包容量大於物品容量時:

dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+p[i]);

else
dp[i][j]=dp[i-1][j];

Code:

二維實現:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue> #include<iostream> #include<stack> using namespace std; int v[110]; int p[110]; int dp[110][10010]; //int main() //{ // int N,W; // scanf("%d%d",&N,&W); // for(int i=1;i<=N;i++) // scanf("%d%d",&v[i],&p[i]); // memset(dp,0,sizeof(dp)); // for(int i=1;i<=N;i++)
// { // for(int j=0;j<v[i]&&j<W;j++) // dp[i][j]=dp[i-1][j]; // for(int j=v[i];j<=W;j++) // dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+p[i]); // } // printf("%d\n",dp[N][W]); //return 0; //} int main() { int N,W; scanf("%d%d",&N,&W); for(int i=1;i<=N;i++) scanf("%d%d",&v[i],&p[i]); memset(dp,0,sizeof(dp)); for(int i=1;i<=N;i++) for(int j=1;j<=W;j++) { if(j>=v[i]) dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+p[i]); else dp[i][j]=dp[i-1][j]; } printf("%d\n",dp[N][W]); return 0; }

一維實現

dp[i]表示在重量為i時能容納的最多價值

Code:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<iostream>
#include<stack>
using namespace std;
int v,p;
int dp[10010];
int main()
{
    int N,W;
    scanf("%d%d",&N,&W);
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=N;i++)
    {
        scanf("%d%d",&v,&p);
        for(int j=W;j>=v;j--)
            dp[j]=max(dp[j],dp[j-v]+p);
    }
    printf("%d\n",dp[W]);
return 0;
}