问题描述:
给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。
转移方程:dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]] + value[i])
不放 放入
其中dp[i][j]表示放入i个物品,总价值为j。
代码如下:
// beibaoproblem.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
#define max(a, b) ( (a) > (b) ? (a) :(b) )
int _tmain(int argc, _TCHAR* argv[])
{
const int v = 10; //最大容量
const int n = 3; //物件的个数
int value[] = {4,5,6};
int weight[] = {3,4,5};
int temp1, temp2;
int i,j;
int dp[n + 1][v + 1];
//初始化
for (i = 0; i < n+1; i++)
for (j = 0; j < v + 1; j++)
{
dp[i][j] = 0;
}
for(i = 1; i <= n; i++)
{
for (j = 1; j <= v; j++)
{
if (j >= weight[i-1])//表示剩余容量大于第i件的容量,可以放入
{
dp[i][j] = max(dp[i-1][j], dp[i-1][j - weight[i-1]] + value[i-1]);
}
else //反之不放入
{
dp[i][j] = dp[i-1][j];
}
}
}
for (i = 0; i < n+1; i++)
{
for (j = 0; j < v + 1; j++)
{
cout << dp[i][j]<<" " ;
}
cout << endl;
}
cout << dp[n][v];
return 0;
}
结果:
-----------------------------------------------------------------------------------------------------
以下是从文件读取:
// beibaoproblem.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
#define FILENAMELENGTH 1000
#define max(a,b) (a) > (b) ? a : b
class CBeibao
{
public:
int m_nNumber; //物品数量
int m_nMaxWeight; //最大载重量
int *m_pWeight; //每个物品的重量
int *m_pValue; //每个物品的价值
int *m_pCount; //每个物品被选中的次数
int m_nMaxValue; //最大价值
public:
CBeibao(const char* filename);
~CBeibao();
int GetMaxValue();
//n表示物品个数,m背包载重量,w数组重量,v价值数组,c是否被选中数组
int GetMaxValue(int n, int m, int *w, int *v, int *c);
void Display(int nmaxValue);
void Display(int nMaxValue, const char* filename);
};
//读入数据
CBeibao::CBeibao(const char* filename)
{
FILE *fp;
fopen_s(&fp, filename, "r");
if (fp == NULL)
{
printf_s("can not open file");
return;
}
fscanf_s(fp, "%d%d", &m_nNumber, &m_nMaxWeight);
m_pWeight = new int[m_nNumber+1];
m_pValue = new int[m_nNumber+1];
//读入每个物品的重量
m_pWeight[0] = 0;
for(int i = 1; i <= m_nNumber; i++)
fscanf_s(fp, "%d", m_pWeight+i);
//读入每个物品的价值
m_pValue[0] = 0;
for(int i = 1; i <=m_nNumber;i++)
fscanf_s(fp, "%d", m_pValue+i);
//初始化每个物品被选中次数为0
m_pCount = new int[m_nNumber+1];
for(int i = 0; i <=m_nNumber;i++)
m_pCount[i] = 0;
fclose(fp);
}
CBeibao::~CBeibao()
{
delete[] m_pWeight;
m_pWeight = NULL;
delete[] m_pValue;
m_pValue = NULL;
delete[] m_pCount;
m_pCount = NULL;
}
int CBeibao::GetMaxValue(int n, int m, int *w, int *v, int *c)//n表示物品个数,m背包载重量,w数组重量,v价值数组,c是否被选中数组
{
int row = n+1;
int col = m+1;
int i,j;
//value[i][j]表示前i个物品能装入载重量为j的背包中物品的最大价值
int **value = new int *[row];
for(i = 0; i < row; i++)
value[i] = new int[col];
//初始化为0
for(i = 0; i < row; i++)
for(j = 0; j < col; j++)
value[i][j] = 0;
//计算
for(i = 1; i < row; i++)
for (j = 1; j < col; j++)
{
if (j >= w[i])
{
value[i][j] = max(value[i-1][j], value[i-1][j - w[i]] + v[i]);
}
else
{
value[i][j] = value[i-1][j];
}
}
//逆推求装入的物品
j = m;
for (i = row - 1; i > 0; i--)
{
if (value[i][j] > value[i-1][j]) //表示第i个物品装入
{
c[i] = 1;
j -= w[i];
}
}
//记录最大价值
int nMaxValue = value[row-1][col-1];
//释放该二维数组
for (i = 0; i < row; i++)
{
delete[col] value[i];
value[i] = NULL;
}
delete[] value;
value = NULL;
return nMaxValue;
}
int CBeibao::GetMaxValue()
{
int nValue = GetMaxValue(m_nNumber, m_nMaxWeight, m_pWeight, m_pValue, m_pCount);
m_nMaxValue = nValue;
return nValue;
}
//显示结果
void CBeibao::Display(int nMaxValue)
{
_tprintf(_T(" %d"), nMaxValue);
for(int i = 1; i <= m_nNumber; i++)
{
if (m_pCount[i])
_tprintf(_T(" %d %d"), i, m_pCount[i]);
}
_tprintf(_T(""));
}
void CBeibao::Display(int nMaxValue, const char* filename)
{
FILE *fp;
fopen_s(&fp, filename, "w");
if (fp == NULL)
{
_tprintf(_T("can not write file!"));
return;
}
fprintf(fp, "%d", nMaxValue);
for (int i = 1; i <= m_nNumber; i++)
{
if (m_pCount[i])
{
fprintf(fp, "%d %d", i, m_pCount[i]);
}
}
fclose(fp);
}
int _tmain(int argc, _TCHAR* argv[])
{
char sinput[10];
char sfilename[FILENAMELENGTH] = "C:\\Users\\sony\\Desktop\\k\\practice\\beibaoproblem\\beibaoproblem\\input.txt";
scanf_s("%s", sinput, _countof(sinput));
while (_stricmp(sinput, "q") != 0)
{
if (_stricmp(sinput, "i") == 0)
{
_tprintf(_T(" please input a filename:"));
/*scanf_s("%s", sfilename);*/
//获取满足最大载重量的最大价值
CBeibao beibao(sfilename);
int nMaxValue = beibao.GetMaxValue();
if (nMaxValue)
{
beibao.Display(nMaxValue);
int nlen = strlen(sfilename);
//这里sfilename表示头指针,sttrcpy表示复制到sfilename + nlen - 4
strcpy_s(sfilename + nlen - 4, FILENAMELENGTH , "_result.txt");
beibao.Display(nMaxValue, sfilename);
}
else
{
_tprintf(_T("error!"));
}
}
_tprintf(_T("input command: "));
scanf_s("%s", sinput);
}
return 0;
}
参考链接:http://blog.youkuaiyun.com/livelylittlefish/article/details/2186206
http://www.cnblogs.com/usa007lhy/archive/2013/05/19/3087195.html