NOIP 2006 T2 金明的预算方案
題目描述
金明今天很開心,家里購置的新房就要領鑰匙了,新房里有一間金明自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說:“你的房間需要購買哪些物品,怎么布置,你說了算,只要不超過NN元錢就行”。今天一早,金明就開始做預算了,他把想買的物品分為兩類:主件與附件,附件是從屬于某個主件的,下表就是一些主件與附件的例子:
主件 附件
電腦 打印機,掃描儀
書柜 圖書
書桌 臺燈,文具
工作椅 無
如果要買歸類為附件的物品,必須先買該附件所屬的主件。每個主件可以有00個、11個或22個附件。附件不再有從屬于自己的附件。金明想買的東西很多,肯定會超過媽媽限定的NN元。于是,他把每件物品規定了一個重要度,分為55等:用整數1-51?5表示,第55等最重要。他還從因特網上查到了每件物品的價格(都是1010元的整數倍)。他希望在不超過NN元(可以等于NN元)的前提下,使每件物品的價格與重要度的乘積的總和最大。
設第jj件物品的價格為v_[j]v[?j],重要度為w_[j]w[?j],共選中了kk件物品,編號依次為j_1,j_2,…,j_kj1?,j2?,…,jk?,則所求的總和為:
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?]。
請你幫助金明設計一個滿足要求的購物單。
輸入輸出格式
輸入格式:
?
第11行,為兩個正整數,用一個空格隔開:
N mNm?(其中N(<32000)N(<32000)表示總錢數,m(<60)m(<60)為希望購買物品的個數。) 從第22行到第m+1m+1行,第jj行給出了編號為j-1j?1的物品的基本數據,每行有33個非負整數
v p qvpq?(其中vv表示該物品的價格(v<10000v<10000),p表示該物品的重要度(1-51?5),qq表示該物品是主件還是附件。如果q=0q=0,表示該物品為主件,如果q>0q>0,表示該物品為附件,qq是所屬主件的編號)
?
輸出格式:
?
一個正整數,為不超過總錢數的物品的價格與重要度乘積的總和的最大值(<200000)。
?
/* 用一個鬼畜的方法寫了出來,開森開森(/≧▽≦)/ */
首先將每一個主件用0/1背包處理,用f[j - v[i]] + p[i]來更新f[i],如果能夠更新,就枚舉這個主件的每一個附件f[j] + p[k]去更新f[j + v[k]](k為附件);如果只是這樣的話,有一種主件會虧,但附件血賺的情況就沒有考慮;所以先將這個主件不更新的值記錄下來,假設這個主件被買,用附件去更新后面,最后再用這個記錄的值去更新到底買不買主件;這段代碼鬼畜的地方在于假設這個點被更新,被更新后還要更新已經被更新過的點,并且最后還要判斷這個點需不需要更新;
#include <bits/stdc++.h>using namespace std;#define ll long long #define INF 0x3f3f3f3f #define MAXN 10100000 #define MAXM 3010 #define _ 0template < typename T > inline void read(T &x) {x = 0;T ff = 1, ch = getchar();while(!isdigit(ch)) {if(ch == '-') ff = -1;ch = getchar();}while(isdigit(ch)) {x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}x *= ff; }int n,m,ans,f[MAXN],v[MAXN],p[MAXN],q[MAXN]; vector < int > a[70];int main() {read(n); read(m);for(int i = 1; i <= m; ++i) {read(v[i]);read(p[i]);read(q[i]);p[i] *= v[i];if(q[i] > 0) a[q[i]].push_back(i);}for(int i = 1; i <= m; ++i) {if(!q[i]) {for(int j = n; j >= v[i]; --j) { // if(f[j - v[i]] + p[i] > f[j]) {int maxx = f[j];f[j] = f[j - v[i]] + p[i]; // } for(int k = 0; k < a[i].size(); ++k) {if(j + v[a[i][k]] <= n && f[j + v[a[i][k]]] < f[j] + p[a[i][k]])f[j + v[a[i][k]]] = f[j] + p[a[i][k]];} if(a[i].size() == 2) {if(j + v[a[i][0]] + v[a[i][1]] <= n && f[j + v[a[i][1]] + v[a[i][0]]] < f[j] + p[a[i][0]] + p[a[i][1]])f[j + v[a[i][1]] + v[a[i][0]]] = f[j] + p[a[i][0]] + p[a[i][1]];} /*if(f[j - v[i]] + p[i] > f[j]) {f[j] = f[j - v[i]] + p[i]; } */ f[j] = max(f[j],maxx); }}}for(int i = 1; i <= n; ++i) ans = max(ans,f[i]);printf("%d\n",ans);return (0^_^0); }?
轉載于:https://www.cnblogs.com/AK-ls/p/10596712.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的NOIP 2006 T2 金明的预算方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 虚拟化(8)_Docker容器
- 下一篇: 迭代和JDB