金明今天很開心,家裏購置的新房就要領鑰匙了,新房裏有一間金明本身專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說:「你的房間須要購買哪些物品,怎麼佈置,你說了算,只要不超過NN元錢就行」。今天一早,金明就開始作預算了,他把想買的物品分爲兩類:主件與附件,附件是從屬於某個主件的,下表就是一些主件與附件的例子:html
主件 附件node
電腦 打印機,掃描儀ios
書櫃 圖書spa
書桌 檯燈,文具設計
工做椅 無code
若是要買歸類爲附件的物品,必須先買該附件所屬的主件。每一個主件能夠有00個、11個或22個附件。附件再也不有從屬於本身的附件。金明想買的東西不少,確定會超過媽媽限定的NN元。因而,他把每件物品規定了一個重要度,分爲55等:用整數1-51−5表示,第55等最重要。他還從因特網上查到了每件物品的價格(都是1010元的整數倍)。他但願在不超過NN元(能夠等於NN元)的前提下,使每件物品的價格與重要度的乘積的總和最大。htm
設第jj件物品的價格爲v_[j]v[j],重要度爲w_[j]w[j],共選中了kk件物品,編號依次爲j_1,j_2,…,j_kj1,j2,…,jk,則所求的總和爲:blog
v_[j_1] \times w_[j_1]+v_[j_2] \times w_[j_2]+ …+v_[j_k] \times w_[j_k]v[j1]×w[j1]+v[j2]×w[j2]+…+v[jk]×w[jk]。get
請你幫助金明設計一個知足要求的購物單。string
輸入格式:
第11行,爲兩個正整數,用一個空格隔開:
N mNm (其中N(<32000)表示總錢數,m(<60)爲但願購買物品的個數。) 從第22行到第m+1m+1行,第jj行給出了編號爲j-1j−1的物品的基本數據,每行有3個非負整數
v p qvpq (其中vv表示該物品的價格(v<10000),p表示該物品的重要度(1-5),qq表示該物品是主件仍是附件。若是q=0,表示該物品爲主件,若是q>0,表示該物品爲附件,qq是所屬主件的編號)
輸出格式:
一個正整數,爲不超過總錢數的物品的價格與重要度乘積的總和的最大值(<200000)。
NOIP 2006 提升組 第二題
【思路】:
金明可選的方案:
只選該主件。
選主件和附件1。
選主件和附件2。
全選
f[j]=max(f[j],f[j-a[i][0].v]+a[i][0].w); f[j]=max(f[j],f[j-a[i][0].v-a[i][1].v]+a[i][0].w+a[i][1].w); f[j]=max(f[j],f[j-a[i][0].v-a[i][2].v]+a[i][0].w+a[i][2].w); f[j]=max(f[j],f[j-a[i][0].v-a[i][2].v-a[i][1].v]+a[i][0].w+a[i][2].w+a[i][1].w);
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<vector> #include<map> #include<string> #include<cstring> using namespace std; const int maxn=999999999; const int minn=-999999999; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int n,m; struct node { int v,w; } a[67][3]; int vis[67],f[320004]; //vis[]判斷是該主件的第幾個附件 int main() { scanf("%d%d",&n,&m); for(int i=1; i<=m; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); if(z==0) { a[i][0].v=x; a[i][0].w=x*y; } else { if(!vis[z]) { a[z][1].v=x; a[z][1].w=x*y; vis[z]=1; } else { a[z][2].v=x; a[z][2].w=x*y; } } } for(int i=1; i<=m; i++) { //m是件數,枚舉從1件到m件這幾種狀況 for(int j=n; j>=0; j--) { //枚舉空間大小 /*只選主件*/ if(j>=a[i][0].v) { f[j]=max(f[j],f[j-a[i][0].v]+a[i][0].w); } /*選主件和附件一*/ if(j>=a[i][0].v+a[i][1].v) { f[j]=max(f[j],f[j-a[i][0].v-a[i][1].v]+a[i][0].w+a[i][1].w); } /*選主件和附件二*/ if(j>=a[i][0].v+a[i][2].v) { f[j]=max(f[j],f[j-a[i][0].v-a[i][2].v]+a[i][0].w+a[i][2].w); } /*全選*/ if(j>=a[i][0].v+a[i][1].v+a[i][2].v) { f[j]=max(f[j],f[j-a[i][0].v-a[i][2].v-a[i][1].v]+a[i][0].w+a[i][2].w+a[i][1].w); } } } printf("%d",f[n]); return 0; }