1.问题重述
给定n种物品和一揹包。物品i的重量是,其价值为,揹包的容量为c。问应如何选择装入揹包中的物品,使得装入揹包中物品的总价值最大?
2.算法分析步骤:
动态规划法:
动态规划与分治法类似,都是把大问题拆分成小问题,通过寻找大问题与小问题的递推关系,解决一个个小问题,最终达到解决原问题的效果,01揹包问题满足最优性原理。
寻找递推关系式,面对当前物品有两种可能性:
包的容量比该物品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j);
还有足够的容量可以装该物品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}
其中V(i-1,j)表示不装,V(i-1,j-w(i))+v(i) 表示装了第i个物品,揹包容量减少 w(i)但价值增加了v(i);
由此可以得出递推关系式:
3.代码描述:
#include<stdio.h>
int c[10][100];//对应每种情况的最大价值
int knapsack(int m,int n)
{
int i,j,w[10],v[10];
printf("请输入每个物品的重量,价值:\n");
for(i=1;i<=n;i++)
scanf("%d,%d",&w[i],&v[i]);
for(i=0;i<10;i++)
for(j=0;j<100;j++)
c[i][j]=0;//初始化数组
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(w[i]<=j)//如果当前物品的容量小于揹包容量
{
if(v[i]+c[i-1][j-w[i]]>c[i-1][j])
c[i][j]=v[i]+c[i-1][j-w[i]];
else
c[i][j]=c[i-1][j];
}
else c[i][j]=c[i-1][j];
}
return (c[n][m]);
}
int main()
{
int m,n;
int i,j;
printf("请输入揹包的容量,物品总个数:\n");
scanf("%d,%d",&m,&n);
printf("揹包能装的最大总价值为%d",knapsack(m,n));
printf("\n");
return 0;
}