【问题】
有n个重量和价值分别为wi ,vi 的物品。从这些物品中挑选出总重量不超过W的物品,求挑选方案中价值总和的最大值。
其中: wi ,vi ,W都是整数 1≤n≤100,1≤wi,vi≤100,1≤W≤10000
【输入】
每一次输入样例由三行组成,第一行有一个整数表示n的值,第二行为n对整数,分别表示第i个物品的重量和价值。第三行表示所挑选物品的最大重量。
【输出】
对于每一次输出样例,输出其最大价值。每一次样例另起一行。
【示例输入】
4
2 3 1 2 3 4 2 2
5
【示例输出】
7
【提示】
令dp[i][j]表示从前 i 个物品中选出总重量不超过 j 的物品时总价值的最大值。
则有:dp[0][j]=0;
dp[i][j] = dp[i-1][j] (j<w[i-1],这里w数组从0开始,因此第 i 项对应 i-1 脚标)
或=max(dp[i-1][j],dp[i-1][j-w[i-1]]+v[i-1]) (j>=w[i-1])
最终dp[n][M]即为所求!
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
【示例代码】
//--------------------------------------【程序说明】-------------------------------------------
// 程序说明:01背包
// 程序描述:动态规划
// IDE版本:Visual Studio 2013
// 作者:Arthur Lee
//------------------------------------------------------------------------------------------------
//【1】头文件
#include <fstream>
#include <ctime>
#include <algorithm> //包括max函数
using namespace std;
#define MAXNUMBER 100
#define MAXWEIGHT 10000
#define TIMER
//【2】函数声明
int DynamicProgram();
void InitialData();
int Search(int, int);
int MemorySearch(int, int);
//【3】定义枚举体,在几种方法中切换
enum Method
{
DynamicProgramming,
NormalSearch,
SearchWithMemory
};
typedef struct tagGoods{
int Weight;
int Value;
}Goods;
//【4】变量声明
Goods AllGoods[MAXNUMBER];
int nCount;
int AvailableWeight;
int DP[MAXNUMBER+1][MAXWEIGHT+1];//保存中间值,DP[i][j]表示前i件商品,其重量不超过j时,所能达到的最大价值。
int main(){
#ifdef TIMER
clock_t start = clock();
#endif // TIMER
ifstream fin("in.txt");
if (fin.fail())
return 1;
ofstream fout("out.txt");
int nValue_temp;
while (!fin.eof())
{
InitialData();
fin >> nCount;
for (int i = 0; i < nCount; ++i)
fin >> AllGoods[i].Weight >> AllGoods[i].Value;
fin >> AvailableWeight;
Method method_temp = Method::SearchWithMemory;
switch (method_temp)
{
case DynamicProgramming:
nValue_temp = DynamicProgram();
break;
case NormalSearch:
nValue_temp = Search(nCount, AvailableWeight);
break;
case SearchWithMemory:
nValue_temp = MemorySearch(nCount, AvailableWeight);
break;
default:
break;
}
fout << "the most value you can achieve is : " << nValue_temp << "\n";
}
#ifdef TIMER
clock_t end = clock();
double duration = (double)(end - start);
fout << "runtime : " << duration << "ms" << endl;
#endif // TIMER
fout.close();
return 0;
}
//【5】函数实现
int DynamicProgram(){
for (int i = 1; i <= nCount; ++i)
for (int j = 0; j <= AvailableWeight; ++j){
if (AllGoods[i - 1].Weight <= j){
DP[i][j] = max(DP[i - 1][j], (DP[i - 1][j - AllGoods[i - 1].Weight] + AllGoods[i - 1].Value));
}
else
DP[i][j] = DP[i - 1][j];
}
return DP[nCount][AvailableWeight];
}
int Search(int i,int j){
int result = 0;
if (i == 0){
return 0;
}
if (AllGoods[i - 2].Weight <= j)
result = max(Search(i - 1, j), Search(i - 1, j - AllGoods[i - 2].Weight) + AllGoods[i - 2].Value);
else
result = Search(i - 1, j);
return result;
}
int MemorySearch(int i, int j){
int result = 0;
if (DP[i][j] > 0)
return DP[i][j];
if (i == 0){
return 0;
}
if (AllGoods[i - 2].Weight <= j)
result = max(MemorySearch(i - 1, j), MemorySearch(i - 1, j - AllGoods[i - 2].Weight) + AllGoods[i - 2].Value);
else
result = MemorySearch(i - 1, j);
DP[i][j] = result;
return result;
}
void InitialData(){
for (int i = 0; i < MAXNUMBER + 1; ++i)
for (int j = 0; j < MAXWEIGHT + 1; ++j)
DP[i][j] = 0;
}