代码
动规类问题,通常可以采用循环或者递归方式来实现。当然所有的递归是否都可以用循环来实现?
#include "stdio.h"
#include "stdlib.h"
/*题设:4个物品,编号1,2,3,4,其价值分别为1,5,8,10,重量为2,3,4,7,总重量不超过10*/
#define TOTAL_NUM 4
#define TOTAL_WEIGHT 10
//为了简化边界处理条件判断的,将下标为0设置为初始值,这个方式屡试不爽
int v[TOTAL_NUM+1] = {0,1,5,8,10};
int w[TOTAL_NUM+1] = {0,2,3,4,7};
int main(void)
{
int dp[TOTAL_NUM+1][TOTAL_WEIGHT+1] = {0}; //记录函数
int trace[TOTAL_NUM+1][TOTAL_WEIGHT+1] = {0}; //标记函数
int num = 0;
int weight = 0;
int repeat = 0;
for(num = 1;num < TOTAL_NUM+ 1; num++)
{
for(weight = 1;weight < TOTAL_WEIGHT + 1; weight++)
{
if(w[num] <= weight) {
repeat = weight/w[num];
if(dp[num - 1][weight-w[num]]+repeat*v[num] >= dp[num - 1][weight]){
dp[num][weight] = dp[num - 1][weight-repeat*w[num]]+repeat*v[num];
trace[num][weight] = num;
continue;
}
}
dp[num][weight] = dp[num - 1][weight];
trace[num][weight]= trace[num - 1][weight];
}
}
printf("\nprofit %d\n",dp[num-1][weight-1]);
}
时间复杂度
由于该问题只有两个变量前k个物品的最大质量为y,所以只需要2个for循环,所以复杂度为物品数目n最大质量w,即O(nw)。
关于动归的背包问题,也有为了减少空间开销而降二维数组压缩成以为动态数组的实现,但是我个人并不喜欢这种方式。原因是因为,我觉得只有最终结果或者最优值是毫无意义的,必须知道最优解是怎么来的,基于二维矩阵可以回溯出获得最优解的具体方案,而对于实际的生产而言,最优解的来源比最优解本身更重要。难道我告诉你从深圳去北京,最快需要10个小时,至于怎么走我不知道。。。这有意义吗?