题目描述
AH 今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过 N 元钱就行”。今天一早 AH 就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的 N 元。于是,他把每件物品规定了一 个重要度,分为 5 等:用整数 1~5 表示,第 5 等最重要。他还从网上查到了每件物品的价格(都是整数元)。他希望在不超过 N 元(可以等于 N 元)的前提 下,使每件物品的价格与重要度的乘积的总和最大。
设第 j 件物品的价格为 v[j],重要度为 w[j],共选中了 k 件物品,编号依次为 j1,j2,……,jk,则所求的总和为:
v[j1]*w[j1]+v[j2]*w[j2]+ …+v[jk]*w[jk]。(其中 * 为乘号)
请你帮助AH设计一个满足要求的购物单。
输入格式
输入的第 1 行,为两个正整数,用一个空格隔开:
N m
(其中 N(<30000)表示总钱 数,m(<25)为希望购买物品的个数。)
从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 2 个非负整数
v p
(其中 v 表示该物品的价格 (v<=10000),p 表示该物品的重要度 (1~5))
输出格式
输出只有一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值(<100000000)。
样例输入
1000 5
800 2
400 5
300 5
400 3
200 2
样例输出
3900
代码
#include <iostream>
#include <algorithm>
using namespace std;
const int N=30000;
const int m=25;
int n,k;
int v,p;
int f[m][N];
int main( )
{
cin>>n>>k;
for(int i=1;i<=k;i++) //物品数量i,总价j 最大价值是i与j的函数,前i件物品最大价值为f[i][j]
{ 最终最大价值当数量增长为k,价钱增长为n,即最大价值为f[k][n]
cin>>v>>p;
p=v*p;
for(int j=0;j<=n;j++)
{ //只需考虑选和不选第i个物品
f[i][j]=f[i-1][j]; //不能放入第i件物品,不需处理
if(j>=v) //能放入第i件物品,但要比较选和不选哪个价值更大。
f[i][j]=max(f[i][j],f[i-1][j-v]+p); //若选,总预算减少了,但是增加了价值
}
}
cout<<f[k][n]<<endl;
return 0;
}
//动态规划:DP,将原问题分解为简单子问题 求解复杂问题的方法。将问题拆分为很多小问题,记录已计算的结果,减少重复运算。
//背包问题:组合优化的NP完全问题。有:01背包、完全背包、多重背包、分组背包
//本题为01背包:给定几种物体,每种物体只有一个,对于每种物体只要考虑选和不选。若不选,不需处理;若选,放入背包。由于不知道之前放入的物品已经占据多少空间,所以需要枚举放入该物体之后占据空间可能的所有情况