【一些题】动态规划:0/1背包问题

以数据结构,算法与应用中第15章为材料

1.先是没有储存中间结果的递归解法(即这种方法没有用到动态规划,就是普通的递归解法)。统计结果+递归次数+运行时间。程序如下:

int F(int i, int y, int n, int *weight, int *value); // 0/1背包问题
static int count_recursive = 0;  //用于调试,统计递归调用次数

int main()
{
	clock_t clockbegin,clockend;
	
	clockbegin = clock();
	
	/*int weight[] = {100, 14, 10};
	int value[] = {20, 18, 15};
	int n = 3, capacity = 116;*/

	int weight[] = {2,2,6,5,4};
	int value[] = {6,3,5,4,6};
	int n = 5, capacity = 10;

	int result = F(0,capacity, n, weight, value);

	clockend = clock();
	cout << clockend-clockbegin << "ms"  << endl;
	cout << "recursive " << count_recursive << " times" << endl;
	cout << result<< endl;
	system("pause");
	
 return 0;
}

int F(int i, int y, int n, int *weight, int *value)
{
	++count_recursive;  用于调试,统计递归调用次数
	int result;
	if(i == n-1)
		{
			result = (y>=weight[n-1])? value[n-1]:0;
			return result;
		}
	if(y<weight[i])
		result = F(i+1, y, n, weight, value);
	else
		result = ( F(i+1,y, n, weight, value)>F(i+1, y-weight[i], n, weight, value)+value[i] ? F(i+1,y, n, weight, value): F(i+1, y-weight[i], n, weight, value)+value[i]);
	return result;
}

在进入“动态规划之前”,先看下这个普通递归的运行结果:

最不对劲的地方是递归进行了99次,而“数据结构,算法与应用”则是进行了28次。

——》有个问题应该出在条件表达式那里:

result = ( F(i+1,y, n, weight, value)>F(i+1, y-weight[i], n, weight, value)+value[i] ? F(i+1,y, n, weight, value): F(i+1, y-weight[i], n, weight, value)+value[i]);

经跟踪调试:

1——》这个语句会先运行F(i+1,y, n, weight, value)>F(i+1, y-weight[i], n, weight, value)部分,这里将有2次直接的调用函数,并且如果每个函数调用没有到直接返回的条件还将进行下一步的递归调用;

2——》执行完这个“>”表达式后,将选择两者其中之一又求值一次,例如F(i+1,y, n, weight, value)较大的话,则又将对F(i+1,y, n, weight, value): F(i+1, y-weight[i], n, weight, value)+value[i])的前半部分再次求值,这会带来一次直接的函数调用+内部可能存在的进一步的递归调用


改变这个地方后,程序变为

int result1 = F(i+1,y, n, weight, value);
int result2 = F(i+1, y-weight[i], n, weight, value)+value[i];
result = ( result1>result2 ? result1: result2);

运行结果为


比书上的递归少了一次(有待继续跟踪

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值