金明的預算(01揹包問題)---------Five-菜鳥級
金明的預算
問題描述
金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間金明自己專用的很寬敞的房間。 更讓他高興的是,媽媽昨天對他說:“你的房間需要購買哪些物品,怎麼佈置,你說了算, 只要不超過N元錢就行”。今天一早,金明就開始做預算了,他把想買的物品分為兩類: 主件與附件,附件是從屬於某個主件的,下表就是一些主件與附件的例子:
主件 附件 電腦 印表機,掃描器 書櫃 圖書 書桌 檯燈,文具 工作椅 無
如果要買歸類為附件的物品,必須先買該附件所屬的主件。每個主件可以有0個、1個或2個附件。 附件不再有從屬於自己的附件。金明想買的東西很多,肯定會超過媽媽限定的N元。於是, 他把每件物品規定了一個重要度,分為5等:用整數1~5表示,第5等最重要。他還從因特網上查到了每件物 品的價格(都是10元的整數倍)。他希望在不超過N元(可以等於N元)的前提下,使每件物品的價格與 重要度的乘積的總和最大。 設第j件物品的價格為v[j],重要度為w[j],共選中了k件物品,編號依次為j_1,j_2,……,j_k, 則所求的總和為: v[j_1]*w[j_1]+v[j_2]*w[j_2]+ …+v[j_k]*w[j_k]。(其中*為乘號) 請你幫助金明設計一個滿足要求的購物單。 輸入格式
輸入檔案budget.in 的第1行,為兩個正整數,用一個空格隔開: N m (其中N(<32000)表示總錢數,m(<60)為希望購買物品的個數。) 從第2行到第m+1行,第j行給出了編號為j-1的物品的基本資料,每行有3個非負整數 v p q (其中v表示該物品的價格(v<10000),p表示該物品的重要度(1~5), q表示該物品是主件還是附件。如果q=0,表示該物品為主件,如果q>0,表示該物品為附件, q是所屬主件的編號)
輸出格式
輸出檔案budget.out只有一個正整數,為不超過總錢數的物品的價格與重要度乘積的總和的 最大值 (<200000)。
樣例輸入
1000 5 800 2 0 400 5 1 300 5 1 400 3 0 500 2 0
樣例輸出
2200
思路: 按主件選取 在有主件的情況下選取附件 題知 附件最多兩個 所以 一個主 可 0,1,2個附件 分情況討論 從而轉化為 01 揹包問題
#include<stdio.h> long int Max(long int a,long int b) {if(a>b)return a; else return b; } int main() { long int w[100], v[100], z1[100]={0},z2[100]={0},q[100]={0}; //存重要度 存價格 存元件1 存元件2 存商品性質 0代表主件 long int dp[100][3201]={0};//dp[i][j]=k 代表 int i,j,n,m; scanf("%d%d",&m,&n); m/=10;//初始化 資料縮小10倍 (因為題目說了都是10的整數倍) for(i=1;i<=n;i++) {scanf("%d%d%d",&v[i],&w[i],&q[i]); v[i]/=10;//資料縮小10倍 (因為題目說了都是10的整數倍) if(q[i]!=0)//不是主件 { if(z1[q[i]]==0) z1[q[i]]=i;//找到對應主件存 元件 1 else z2[q[i]]=i; } } v[0]=w[0]=q[0]=0;//揹包初始化 for(i=1;i<=n;i++)// 列舉物品數 for(j=1;j<=m;j++)//列舉錢數 if(v[i]<=j&&q[i]==0)//判斷主件 { dp[i][j]=Max(dp[i-1][j],dp[i-1][j-v[i]]+v[i]*w[i]);//不配元件 單主件 if(v[z1[i]]+v[i]<=j)dp[i][j]=Max(dp[i][j],dp[i-1][j-v[z1[i]]-v[i]]+v[i]*w[i]+v[z1[i]]*w[z1[i]]);//配 附件 1 if(v[z2[i]]+v[i]<=j)dp[i][j]=Max(dp[i][j],dp[i-1][j-v[z2[i]]-v[i]]+v[i]*w[i]+v[z2[i]]*w[z2[i]]);//配 附件 2 if(v[z1[i]]+v[z2[i]]+v[i]<=j)dp[i][j]=Max(dp[i][j],dp[i-1][j-v[z1[i]]-v[i]-v[z2[i]]]+v[i]*w[i]+v[z1[i]]*w[z1[i]]+v[z2[i]]*w[z2[i]]);//配兩附件 }else dp[i][j]=dp[i-1][j];//不取 printf("%ld",dp[n][m]*10); return 0;}