藍橋杯 - 金明的預算方案

問題描述
  金明今天很開心,家裏購置的新房就要領鑰匙了,新房裏有一間金明自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說:“你的房間需要購買哪些物品,怎麼佈置,你說了算,只要不超過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
參考了 https://www.cnblogs.com/mrlaker/archive/2012/07/17/2595345.html 的博文,侵刪!


import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		int n=input.nextInt();
		int m=input.nextInt();
		
		int  v[]=new int[m+1];
		int  w[]=new int[m+1];
		int  p[]=new int[m+1];
		int dp[]=new int[n+1];
		
		int  a[][] = new int[m+1][2];
		int ww[][] = new int[m+1][4];
		int vv[][] = new int[m+1][4];
		
		for(int i=1;i<=m;i++)
		{
			v[i]=input.nextInt();
			w[i]=input.nextInt();
			p[i]=input.nextInt();
		
			if(p[i]!=0)
			{
				if(a[ p[i] ][0]==0)
					a[ p[i] ][0]=i;
				else
					a[ p[i] ][1]=i;
			}
		}
		input.close();
		
		for(int i=1;i<=m;i++)
		{
			if(p[i]==0)
			{
				ww[i][0] = v[ i ] * w [ i ];
				ww[i][1] = v[ a[i][0] ] * w[ a[i][0] ] + ww[i][0];
				ww[i][2] = v[ a[i][1] ] * w[ a[i][1] ] + ww[i][0];
				ww[i][3] = v[ a[i][0] ] * w[ a[i][0] ] + v[ a[i][1] ] * w[ a[i][1] ] + ww[i][0];
					
				vv[i][0] = v[i];
				vv[i][1] = v[i] + v[ a[i][0] ];
				vv[i][2] = v[i] + v[ a[i][1] ];
				vv[i][3] = v[i] + v[ a[i][0] ] + v[ a[i][1] ];
			}
		}
		
		for(int i=1;i<=m;i++)
			for(int j=n;j>=v[i];j--)
			{
				if(p[i]==0)
				{
					for(int k=0;k<4;k++)
						if(j>=vv[i][k])
							dp[j]=Math.max(dp[j], dp[j-vv[i][k]]+ww[i][k]);
				}
//				else 
//					for(int k=0;k<4;k++)
//						if(j>=vv[i][k])
//							dp[j]=Math.max(dp[j], dp[j-v[i]]+w[i]);
			}
		System.out.println(dp[n]);
	}
	
}

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