這道題應該是背包問題裡堪稱經典的問題了,表示剛開始學DP,這類問題也很快弄懂了。
題目大意是給你一些分組,每組物品放在一個盒子裡,每組物品都有幾種物品,有自己的價格c和價值v,現在要買一個物品時,要買它對應的盒子,盒子的價格是p,問你花一定的錢最多買到的物品價值是多少。
這類問題要用到兩個數組,dp[0][i]表示i塊錢可以買到的最大價值,dp[1][i]表示考慮到當前盒子時,i塊錢可以買到的最大價值,首先dp[0]置為0,枚舉全部的盒子,dp[1]置為-oo表示買不到,更新的轉移可以從dp[0]轉移也可以從dp[1]轉移,從dp[0]跳躍表示你還沒有買盒子,要附加上盒子的價格,dp[1]表示你買過盒子了,就直接轉移就可以了,轉移方程如下:
dp[1][k]=max(dp[1][k],dp[1][k-c[i][j]]+v[i][j],dp[0][k-c[i][j]-p[i]]+v[i][j]);
注意每次dp[1]的置-oo操作,以及每次枚舉完當前盒子後用dp[1]更新dp[0]的值。
dp[0][j]=max(dp[0][j],dp[1][j]);
我的完整代碼:
#include <cstdio><br />#include <cstring><br />#include <cstdlib><br />#include <algorithm><br />using namespace std;<br />const int oo=0x3f3f3f3f;<br />int dp[2][100100];<br />int p[60],m[60];<br />int c[60][12],v[60][12];<br />int main(){<br /> int n,w;</p><p> while(~scanf("%d%d",&n,&w)){<br /> for(int i=0;i<n;i++){<br /> scanf("%d%d",&p[i],&m[i]);<br /> for(int j=0;j<m[i];j++){<br /> scanf("%d%d",&c[i][j],&v[i][j]);<br /> }<br /> }<br /> for(int i=0;i<=w;i++){<br /> dp[0][i]=0;<br /> }</p><p> for(int i=0;i<n;i++){<br /> for(int j=0;j<=w;j++){<br /> dp[1][j]=-oo;<br /> }<br /> for(int j=0;j<m[i];j++){<br /> for(int k=w;k>=c[i][j];k--){<br /> if(dp[1][k-c[i][j]]>=0<br /> &&dp[1][k]<dp[1][k-c[i][j]]+v[i][j])<br /> dp[1][k]=dp[1][k-c[i][j]]+v[i][j];<br /> if(k>=c[i][j]+p[i])<br /> dp[1][k]=max(dp[1][k],dp[0][k-c[i][j]-p[i]]+v[i][j]);<br /> }<br /> }<br /> for(int j=0;j<=w;j++){<br /> dp[0][j]=max(dp[0][j],dp[1][j]);<br /> }<br /> }<br /> printf("%d/n",*max_element(dp[0],dp[0]+w+1));<br /> }</p><p> return 0;<br />}<br />