动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再合并子问题的解以得出原问题的解。 通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量: 一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。 这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。
#include <stdio.h>
const int W=30; //背包容量
const int N=3; //物品个数
int c[N+1][W+1]; //矩阵存储最优值
//int maxv=0;
//完成对矩阵的填充
void f(int v[],int w[]){
int i,j;
c[0][0]=0;
for(i=1;i<=N;i++){
c[i][0]=0;
}
for(i=0;i<=W;i++){
c[0][i]=0;
}
for(i=1;i<=N;i++){
for(j=1;j<=W;j++){
if(w[i]>j){ //当w[i]>j时 第i个物品不装入背包
c[i][j]=c[i-1][j];
}else{
if(c[i-1][j]>(v[i]+c[i-1][j-w[i]])){ //w[i]<=j,且第i个物品装入背包后的价值<value[i-1][j] 最优值不变
c[i][j]=c[i-1][j];
}else{
c[i][j]=v[i]+c[i-1][j-w[i]]; //w[i]<=j,且第i个物品装入背包后的价值>value[i-1][j],则记录当前最大价值
//maxv+=c[i][j];
}
}
}
}
}
int main(){
int w[N+1],v[N+1],i,j;
for(i=1;i<=N;i++){
printf("请输入第%d件物品的重量和价值",i);
scanf("%d%d",&w[i],&v[i]);
printf("\n");
}
f(v,w);
j=W;
printf("选中物品的重量为:\n");
for(i=N;i>=1;i--){ //将矩阵向前逆推
if(c[i][j]>c[i-1][j]){ //c[i][j]>c[i-1][j] 第n个物品被装入背包
printf("%d ",w[i]);
j-=w[i]; //前n-1个物品被装入W-w[n] 的背包中
}
}
// printf("\n%d",maxv);
return 0;
}