題目: 開心的小明
描述
小明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間他自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說:“你的房間需要購買哪些物品,怎麼布置,你說了算,只要不超過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:思路:DP 0/1背包
2:其實只要理解了題目就會發現,只要把等級和價格成積看成是0/1背包的價值,然後把價格看成重量就可以直接按照0/1背包思路做了
3:0/1背包, 假設當前背包可以裝的重量為j;
如果j >= w[i],說明第i個物品能夠被背包裝下,這時考慮是裝下得到的價值大還是不裝下得到的價值大,那麼就有 dp[j] = max(dp[j-w[i]]+v[i] , dp[j]).用dp[j]表示背包可以裝下的重量為j時候可以得到的最大價值
代碼:
[cpp]
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
using namespace std;
#define MAXN 100010
int t , n , m;
int w[MAXN] , v[MAXN];
int dp[MAXN];
int max(int a , int b){
return a>b?a:b;
}
void solve() {
int i , j;
memset(dp , 0 , sizeof(dp));
for(i = 0 ; i < m ; i++){
for(j = n ; j >= 0 ; j--){
if(j >= w[i]){
dp[j] = max(dp[j-w[i]]+v[i] , dp[j]);
}
}
}
printf("%d\n" , dp[n]);
}
int main() {
//freopen("input.txt" , "r" , stdin);
int a , b;
scanf("%d%*c" , &t);
while(t--){
scanf("%d%d*c" , &n , &m);
for(int i = 0 ; i < m ; i++){
scanf("%d%d*c" , &a , &b);
w[i] = a ; v[i] = a*b;
}
solve();
}
return 0;
}