///////////动态规划解背包问题////////////
动态规划:对大问题进行小问题分解
情况1:物品1放入背包,对应子问题:背包容量减少物品1体积后,对剩余物品求解
情况2:物品1不放入背包,对应子问题:背包容量不变,对剩余物品求解。
使用结构体:
item{int value;int volume;} //保存物品的价值与体积
memory(int IfIn,valueSum,volumeSum) //保存结果
函数说明: DynamicToPackage (item ite[],int save[][])
输入: item ite[] //节点信息
int save[][] //保存结果二维表
输出: 返回结果二维表save
算法简析:
for (i : each node)
for (j : maxVol) //从0开始对每个物品进行各种剩余背包容量情况计算
if (node.vol<=j) //如果当前节点可以放入当前背包剩余容量
if (value up) //如果当前物品放入背包总价值增加
node in //记录节点放入背包信息
else //如果当前物品放入背包总价值不增加
node no in //记录节点不放入背包信息
else //如果当前节点不可以放入当前背包剩余容量
node no in //记录节点不放入背包信息
////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define MAX 3 //物品数
#define maxVol 10 //背包容量
//#define MAX 6 //物品数
//#define maxVol 21 //背包容量
{
int value; //物品价值
int volume; //物品体积
} item;
{
bool IfIn; //是否放入背包
int valueSum; //背包内价值总和
int volumeSum; //背包内体积总和
} memory;
void print (memory save[MAX][maxVol+1],item ite[]); //输出结果
void DynamicToPackage (item ite[],memory save[MAX][maxVol+1]);
///////////////////////////////////////////
{
//int value[MAX] = {20,15,15,10,30,60}; //物品价值
//int volume[MAX] = {3,6,5,2,4,8}; //物品体积
int value[MAX] = {4,5,6}; //物品价值
int volume[MAX] = {3,4,5}; //物品体积
item ite[MAX]; //保存物品信息
memory save[MAX][maxVol+1]; //保存图表
makeItem (value,volume,ite);//将物品信息保存到结构体
DynamicToPackage (ite,save);
print (save,ite);
return 0;
}
void makeItem (int value[],int volume[],item ite[])
{
int i;
for (i=0; i<MAX; i++)
{
ite[i].value = value[i];
ite[i].volume = volume[i];
}
}
void print (memory save[MAX][maxVol+1],item ite[])
{
int i,j;
printf ("生成的表(是否放入背包,背包内物品总体积,背包内物品总价值):\n");
for (i=0; i<=maxVol; i++)
{
for (j=0; j<MAX; j++)
printf ("(%d,%d,%d) ",save[j][i].IfIn,save[j][i].volumeSum,save[j][i].valueSum);
printf ("\n");
}
printf ("背包容量为:%d\n",maxVol);
printf ("放入背包的物品组成为(价值,体积):");
for (i=MAX-1,j=maxVol; i>= 0; i--)
{
if (save[i][j].IfIn)
{
printf ("(%d,%d) ",ite[i].value,ite[i].volume);
j = j - ite[i].volume;
}
}
printf ("\n总价值为:%d 总使用体积为:%d\n",save[MAX-1][maxVol].valueSum,save[MAX-1][maxVol].volumeSum);
}
void DynamicToPackage (item ite[],memory save[MAX][maxVol+1])
{
int i,j; //i--节点 j--剩余背包容量
for (j=0; j<=maxVol; j++)
{
if (ite[0].volume <= j)
{
save[0][j].valueSum = ite[0].value;
save[0][j].IfIn = true;
save[0][j].volumeSum = ite[0].volume;
}
else
{
save[0][j].valueSum = 0;
save[0][j].IfIn = false;
save[0][j].volumeSum = 0;
}
}
for (i=1; i<MAX; i++) //对每个节点进行计算
{
for (j=0; j<=maxVol; j++) //从0开始对每个物品进行各种剩余背包容量情况计算
{
if (ite[i].volume <= j) //如果当前节点可以放入当前背包剩余容量
{//如果 减去当前物品体积下前面的最大价值 + 当前物品价值 >= 前面物品在体积j的最大价值
if (save[i-1][j-ite[i].volume].valueSum+ite[i].value >= save[i-1][j].valueSum)
{
save[i][j].IfIn = true;
save[i][j].valueSum = save[i-1][j-ite[i].volume].valueSum + ite[i].value;
save[i][j].volumeSum = save[i-1][j-ite[i].volume].volumeSum + ite[i].volume;
}
else
{
save[i][j].IfIn = false;
save[i][j].valueSum = save[i-1][j].valueSum;
save[i][j].volumeSum = save[i-1][j].volumeSum;
}
}
else //如果当前节点不可以放入当前背包剩余容量
{
save[i][j].IfIn = false;
save[i][j].valueSum = save[i-1][j].valueSum;
save[i][j].volumeSum = save[i-1][j].volumeSum;
}
}
}
}