这次做动态规划是用的二维数组来写,一维数组还没有想,如果以后做了会再补充。下面我们来开始了解:
动态规划的特性和基础知识可以参考相关书籍,这次主要讲解背包问题的详细理解。
题目:有n件物品和一个容量为v的背包。第i件物品的重量是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
我们可以来参考这个表来进行思路理解。
这个表是按从上到下的顺序开始的,咱们应该知道填写的原则,那就是使背包中物品价值总和最大。
大家可以先自己长试着写这个表,看自己写的是否正确。
然后我们从这个表中来找一下规律。例如:有4件物品,背包容量为10,那么根据表里面填的我们知道最大价值和为14。那这个数肯定不是一下子得来的,它需要前面的累积。重点是这个积累的过程,它涉及到排除和比较。下面是代码,我会重点进行逐步解释。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 1001
int ans[N][N];//二维数组,记录的是表中每个的最大价值总和
int n,v,c[N],w[N];
int max(int a,int b)
{
if(a>=b)
return a;
else
return b;
}
int main()
{
int max(int,int);
while(scanf("%d%d",&n,&v))//读取数量和容量
{
if(n==0&&v==0)
return 0;//这个是说n和v同时为0是结束程序
int i,j;
memset(ans,0,sizeof(ans));//数组初始化,每个都赋值为0.
for(i=1;i<=n;i++)
{
scanf("%d%d",&c[i],&w[i]);//读取n个物体的重量和价值
}
//以下是背包问题的核心部分
for(i=1;i<=n;i++)//因为得到我们需要的解是需要前面上一步的结果,所以,此时定义i从1开始,而不是从零开始
{//i控制的是物品个数,j则是背包的容量大小
for(j=v;j>0;j--)//j一定要大于零,背包容量不能为零
{
if(j<c[i])//这里需要加以判断,否则会出现得到的是初值0,而不是上一步的值
ans[i][j]=ans[i-1][j];//因为容量不够,所以不能装下,直接得到上一步的值。
else
ans[i][j]=max(ans[i-1][j],ans[i-1][j-c[i]]+w[i]);//这里就是判断最大值
//而ans[i-1][j-c[i]]+w[i]举个例子进行讲解。
//例如图中,当得出ans[4][10]的最大价值和那么那个式子可化成:
//ans[3][10-c[4]]+w[4]=ans[3][5]+4=9+4=13,没有ans[3][10]=14大,所以得出答案14。
printf("%5d",ans[i][j]);
}
printf("\n");
}
}
return 0;
}
这个是程序的运行结果,我是按表出值的,和表反了一下,应该可以看懂的。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 1001
int ans[N][N];//二维数组,记录的是表中每个的最大价值总和
int n,v,c[N],w[N];
int max(int a,int b)
{
if(a>=b)
return a;
else
return b;
}
int main()
{
int max(int,int);
while(scanf("%d%d",&n,&v))//读取数量和容量
{
if(n==0&&v==0)
return 0;//这个是说n和v同时为0是结束程序
int i,j;
memset(ans,0,sizeof(ans));//数组初始化,每个都赋值为0.
for(i=1;i<=n;i++)
{
scanf("%d%d",&c[i],&w[i]);//读取n个物体的重量和价值
}
//以下是背包问题的核心部分
for(i=1;i<=n;i++)//因为得到我们需要的解是需要前面上一步的结果,所以,此时定义i从1开始,而不是从零开始
{//i控制的是物品个数,j则是背包的容量大小
for(j=v;j>0;j--)//j一定要大于零,背包容量不能为零
{
if(j<c[i])//这里需要加以判断,否则会出现得到的是初值0,而不是上一步的值
ans[i][j]=ans[i-1][j];//因为容量不够,所以不能装下,直接得到上一步的值。
else
ans[i][j]=max(ans[i-1][j],ans[i-1][j-c[i]]+w[i]);//这里就是判断最大值
//而ans[i-1][j-c[i]]+w[i]举个例子进行讲解。
//例如图中,当得出ans[4][10]的最大价值和那么那个式子可化成:
//ans[3][10-c[4]]+w[4]=ans[3][5]+4=9+4=13,没有ans[3][10]=14大,所以得出答案14。
printf("%5d",ans[i][j]);
}
printf("\n");
}
}
return 0;
}