nyoj 49-開心的小明(動態規劃, 0-1背包問題)
阿新 • • 發佈:2018-05-29
限定 std btn inpu 描述 背包 代碼 OS 出了
49-開心的小明
內存限制:64MB
時間限制:1000ms
Special Judge: No
accepted:7
submit:11
題目描述:
小明今天很開心,家裏購置的新房就要領鑰匙了,新房裏有一間他自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說:“你的房間需要購買哪些物品,怎麽布置,你說了算,只要不超過N 元錢就行”。今天一早小明就開始做預算,但是他想買的東西太多了,肯定會超過媽媽限定的N 元。於是,他把每件物品規定了一個重要度,分為5 等:用整數1~5 表示,第5 等最重要。他還從因特網上查到了每件物品的價格(都是整數元)。他希望在不超過N 元(可以等於N 元)的前提下,使每件物品的價格與重要度的乘積的總和最大。設第j 件物品的價格為v[j],重要度為w[j],共選中了k 件物品,編號依次為j1...jk,則所求的總和為:v[j1]*w[j1]+..+v[jk]*w[jk]請你幫助金明設計一個滿足要求的購物單.輸入描述:
第一行輸入一個整數N(0<N<=101)表示測試數據組數 每組測試數據輸入的第1 行,為兩個正整數,用一個空格隔開: N m (其中N(<30000)表示總錢數,m(<25)為希望購買物品的個數。) 從第2 行到第m+1 行,第j 行給出了編號為j-1 的物品的基本數據,每行有2 個非負整數 v p (其中v 表示該物品的價格(v≤10000),p 表示該物品的重要度(1~5))
輸出描述:
每組測試數據輸出只有一個正整數,為不超過總錢數的物品的價格與重要度乘積的總和的 最大值(<100000000)
樣例輸入:
1 1000 5 800 2 400 5 300 5 400 3 200 2
樣例輸出:
3900
分析:
1、0-1背包問題(總共只有n的空間,每個物體要消耗m個空間,問最大可以裝下多少價值的東西)
2、狀態方程:A[i][v] = max(A[i-1][v], A[i-1][v-w[i]] + p[i]);
狀態壓縮:A[i] = max(A[i], A[i-v] + v*w);
核心代碼:
1 while(m --) 2 { 3 scanf("%d%d", &v, &w); 4 for(int i = n; i >= v; ++ i) 5 A[i] = max(A[i], A[i-v] + v*w); 6 //A[n] 即就是最優解 7 }
C/C++代碼實現(AC);
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 #include <stack> 7 #include <map> 8 #include <queue> 9 #include <set> 10 11 using namespace std; 12 const int MAXN = 30010; 13 14 int main() 15 { 16 17 int t, A[MAXN]; 18 scanf("%d", &t); 19 while(t --) 20 { 21 int n, m, v, b; 22 memset(A, 0, sizeof(A)); 23 scanf("%d%d", &n, &m); 24 while(m --) 25 { 26 scanf("%d%d", &v, &b); 27 for(int i = n; i >= v; -- i) 28 A[i] = max(A[i], A[i-v] + v*b); 29 //A[i][v] = max(A[i-1][v], A[i-1][v-w[i]] + p[i]) 30 //即就是考慮每一個滿足條件的元素的局部最大 31 } 32 printf("%d\n", A[n]); 33 } 34 return 0; 35 }
nyoj 49-開心的小明(動態規劃, 0-1背包問題)