两天的时间都在学习动态规划:小作业(01背包问题:)
数据结构老师布置的这个小作业还真是让人伤头脑,自己实在想不出来了便去网上寻找讲解,看到一篇不错的文章:
http://www.cnblogs.com/sdjl/articles/1274312.html -------通过金矿模型介绍动态规划
但是----------------------------------------
两天的时间才完成这个lab
总结:1.思维思路要清晰。2.题目信息要看清楚。3.改代码过程中注意小变量的数值是否同步变化。
01背包问题思路(自顶向下):
背包承重为U。假设有十个物品,从左往右依次编号排列,可以采取如下步骤:
1.站在第10个物品处,一个物品只有选择和未被选择两种情况,如果选择了当前物品,那么选了它之后跟不选它所得到的价值谁大一点?其实我们采用递归两种情况都会考虑的
i:当前物品重量大于U,那肯定就不能选择这个物品,直接就考虑前9个物品的选择情况了,此时去看第九个物品。
ii:当前物品重量小于U,可以选择也可以不选择,但是我们要看哪种情况更好,更优:选择这个物品,假设前9个物品的选择最优情况(此时背包容量会变小,因为选择了第10个物品)我们已经得知了,此时可以得到在选择第10个物品的情况下的价值,而如果不选择这个物品,那么我们同样假设前9个物品的最优选择情况(此时背包容量还是U)已经得知了,那么我们从这选与不选的两种情况中选择最大的一种方案下就是原问题的最优解了。
iii:这是递归的过程,每个问题都需要有前面的最好的选择方案才可以得出最优解,所以需要一个递推边界情况,当考虑第一个物品的时候,也就是考虑的物品中剩余的最后一个的时候,如果不选,因为前面已经没有物品了,所以什么也放不进背包,得到的价值是0;如果选了,那就是当前物品的价值。
贴代码:
#include<stdio.h> #include<math.h> #include<string.h> int max_o,max_w; #define max_o (3) #define max_w (50) int weight[max_o]; //用来存储物品重量 int value[max_o]; //用来存储物品价值 int pri[max_o]; //用来标记物品是否被选择 int maxval[max_o]; //用来作备忘 void inia() { int j; for(j=0;j<max_o;j++) maxval[j]=0; } void inib() { int j; for(j=0;j<max_o;j++) { pri[j]=0; } } int max(int a,int b) { return a>b?a:b; } int getmax(int maxweight,int max_n) { int maxret; int o,k; if(maxval[max_n]!=0) return maxval[max_n]; if(max_n==0) { if(weight[max_n]>maxweight) maxret=0; else { maxret=value[max_n]; pri[max_n]=max_n; } } else if(weight[max_n]<=maxweight) { o=getmax(maxweight-weight[max_n],max_n-1)+value[max_n]; k=getmax(maxweight,max_n-1); if(o>k) pri[max_n]=max_n; maxret=max(o,k); } else { maxret = getmax(maxweight,max_n-1); } maxval[max_n] = maxret; return maxret; } void main() { int i; inia(); inib(); for(i=0;i<max_o;i++) { scanf("%d%d",&weight[i],&value[i]); } printf("%d ",getmax(max_w,max_o-1)); for(i=0;i<max_o;i++) { if(pri[i]!=0) printf("第%d个物品被选择 ",pri[i]+1); } }