1. 程式人生 > >算法提高 金明的預算方案

算法提高 金明的預算方案

專用 開始 pla isp 預算 他還 include printf efi

問題描述   金明今天很開心,家裏購置的新房就要領鑰匙了,新房裏有一間金明自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說:“你的房間需要購買哪些物品,怎麽布置,你說了算,只要不超過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 思路 : 可以看出01背包的變種,價格相當於重量 , 價格乘重要度相當於價值 然後大致分為下面五種情況: (1) 什麽也不選 (2)選主件 (3)選主件加第一個附件 (4)選主件加第二個附件 (5)選主件加兩個附件 有的有附件有的沒有附件 就是0~2個 假設都有附件,如果沒有,就是0*0,對結果沒有影響,多判斷幾次也不會耗費太長時間
 1
#include<stdio.h> 2 #include<stdlib.h> 3 4 #define Max(a,b) (a>b)?(a):(b) 5 #define M 61 6 #define N 33000 7 8 void input( int [][3] , int [][3] , int ); 9 int maxMoney( int [][3] , int [][3] , int , int ); 10 11 int main(void){ 12 int n , m ; 13 scanf("%d%d", &n , &m );
14 15 int v[M][3] = {0} , p[M][3] = {0} ; 16 17 input( v , p , m ); 18 19 printf("%d\n", maxMoney( v , p , m , n ) ); 20 return 0; 21 } 22 23 int maxMoney( int v[][3] , int p[][3] , int m , int n ){ 24 static int dp[M][N] = {0} ; 25 int i , j , k ; 26 for( i = 1
; i <= m ; i ++ ){ 27 for( j = 1 ; j <= n ; j ++ ){ 28 if( j-v[i][0] >= 0 ){ 29 dp[i][j] = Max( dp[i-1][j] , dp[i-1][j-v[i][0]] + v[i][0] * p[i][0] ); 30 //0號主件 31 if( j-v[i][0]-v[i][1] >= 0 ){ 32 dp[i][j] = Max( dp[i][j] , dp[i-1][j-v[i][0]-v[i][1]] + v[i][0] * p[i][0] + v[i][1] * p[i][1] ); 33 //選擇1號附件 34 } 35 if( j-v[i][0]-v[i][2] >= 0 ){ 36 dp[i][j] = Max( dp[i][j] , dp[i-1][j-v[i][0]-v[i][2]] + v[i][0] * p[i][0] + v[i][2] * p[i][2] ); 37 //選擇2號附件 38 } 39 if( j-v[i][0]-v[i][1]-v[i][2] >= 0 ){ 40 dp[i][j] = Max( dp[i][j] , dp[i-1][j-v[i][0]-v[i][1]-v[i][2]] + v[i][0] * p[i][0] + v[i][1] * p[i][1] + v[i][2] * p[i][2] ); 41 //選擇1號和2號附件 42 } 43 } else { 44 dp[i][j] = dp[i-1][j] ; 45 } 46 } 47 } 48 return dp[m][n]; 49 } 50 51 void input( int v[][3] , int p[][3] , int n ){ 52 int i , tv , tp , tq ; 53 for( i = 1 ; i <= n ; i ++ ){ 54 scanf("%d%d%d", &tv , &tp , &tq ); 55 if( tq == 0 ){ 56 v[i][0] = tv , p[i][0] = tp ; 57 //填充0號主件 58 } else if( v[ tq ][1] == 0 ){ 59 v[ tq ][1] = tv , p[ tq ][1] = tp; 60 //填充1號附件 61 } else { 62 v[ tq ][2] = tv , p[ tq ][2] = tp; 63 //填充2號附件 64 } 65 } 66 }

算法提高 金明的預算方案