小明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早小明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的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]。(其中*为乘号)
请你帮助小明设计一个满足要求的购物单。
#include "OJ.h"
#include <stdlib.h>
#include <vector>
using namespace std;
/*
功能:
输入参数:int*p 指向二维数组的首地址,该二维数组第0行的两个数分别表示:总钱数<30000,和希望购买物品的个数<25;
该数组从第1行到第m行(1<=j<=m)中给出了编号为j的物品的基本数据,每行有2个非负整数,
表示该物品的价格(<=10000)和该物品的重要度(1~5)。
GetResult表示不超过总钱数的物品的价格与重要度乘积的总和的最大值(<100000000)。
不需做入参检查,测试用例可以保证~
例如:4000 8(第0行)
821 3 (第1行)
422 5
458 5
500 3
200 2
430 4
530 3
239 3
则表示 总钱数为4000,希望购买物品个数为8个,因此从第1行到第8行表示编号为j的物品的价格及物品的重要度。
返回值:无
温馨提示:根据题意可知,该二维数组只有两列,且行数为第0行的第二个元素数值+1;入参p不能按照二维数组的方法来取值,要将
二维的转换成一维的哦~
*/
//方法一:01背包问题
void GetResult_1(int*p,int& Get_Result)
{
// 在这里实现功能
if(NULL == p)
{
return;
}
vector<int> w;//钱
vector<int> v;//重要度
int money = p[0];
int num = p[1]; //物品数量
//解析数据
for(int i=1; i<=num; i++)
{
w.push_back(p[i*2]);
v.push_back(p[i*2+1]);
}
//状态矩阵
vector<vector<int> > dp(num+1, vector<int>(money+1, 0));
int i=1; //行索引,代表第i件物品;
int j=1; //列索引,代表money
for(i=1; i<=num; i++)
{
for(j=1; j<=money; j++)
{
if(w[i-1] > j)
{
dp[i][j] = dp[i-1][j];
}
else
{
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i-1]] + w[i-1]*v[i-1]);
}
}
}
Get_Result = dp[i-1][j-1];
}
//方法二:节省空间的01背包
void GetResult(int*p,int& Get_Result)
{
// 在这里实现功能
if(NULL == p)
{
return;
}
int num = p[1]; //物品数量
int money = p[0]; //钱数
//状态矩阵
vector<int> dp(money+1, 0);
int i=1; //行索引,代表第i件物品;
int j=1; //列索引,代表money
for(i=1; i<=num; i++)
{
int w = p[i*2];
int v = p[i*2+1];
for(j=money; j>=w; j--)
{
dp[j] = max(dp[j], dp[j-w]+v*w);
}
}
Get_Result = dp[money];
return;
}