动态规划解决分割问题

关于钢条切割问题的具体描述请看下面的博客:

http://www.cnblogs.com/tgycoder/p/4980655.html

写的很不错,基本把算法导论上的这一章的精华都写出来了,我也贴出我的代码,基本和书上差不多,只是把伪代码转化为可以运行的C++代码,代码转换的过程中也加深了对算法的理解。

代码如下:

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;

int p[] = { 0,1,5,8,9,10,17,17,20,24,30 };  //钢条价格表


/*自顶向下递归实现钢条切割问题*/
int Cut_Rod(int p[], int n)
{
	if (n == 0)
	{
		return 0;
	}
	int q = -65535;    //此变量记录最大收益
	for (int i = 1; i <= n; i++)
	{
		q = max(q, p[i] + Cut_Rod(p, n - i));
	}
	return q;
}


/*自顶向下带记录递归实现钢条切割问题*/
int Memoized_Cut_Rod_Aux(int *p, int n,int r[])
{
	int q;
	if (r[n] >= 0)
		return r[n];
	if (n == 0)
		q = 0;
	else
	{
		q = -65535;
		for (int i = 1; i <= n; i++)
		{
			q = max(q, p[i] + Memoized_Cut_Rod_Aux(p, n - i, r));
		}
	}
	r[n] = q;
	return q;
		
}




int Memoized_Cut_Rod(int *p,int n)
{
	int r[11];   //此处改为动态分配内存比较好
	for (int i = 0; i <= n; i++)
	{
		r[i] = -65536;
	}

	return Memoized_Cut_Rod_Aux(p, n, r);
}

/*自底向上实现钢条切割问题*/
int Bottom_up_Cut_Rod(int p[], int n, int s[])
{
	int r[11];
	//int s[11];   //用来记录具体的切割方案
	
	r[0] = 0;
	for (int j = 1; j <= n; ++j)
	{
		int q = -65535;
		for (int i = 1; i <= j; ++i)
		{
			if (q < p[i] + r[j - i])
			{
				q = p[i] + r[j - i];
				s[j] = i;
			}
			
		}
		r[j] = q;

	}
	return r[n];
}


void print_sn(int *s,int n)
{
	while (n > 0)
	{
		cout << s[n];
		n = n - s[n];
	}
	cout << endl;
}



int main()
{

	//cout << Cut_Rod(p, 7) << endl;
	//cout << Memoized_Cut_Rod(p, 7) << endl;

	int *s = new int[11];   //用来记录具体的分割方案
	cout << Bottom_up_Cut_Rod(p, 9,s) << endl;
	print_sn(s, 9);

	return 0;
}

  第一次接触动态规划,我认为动态规划的关键在于可以解决子问题重叠的情况,即不同的子问题具有公共的子子问题,动态规划对其中的子子问题只求解一次,并把结果保存下来,避免做相同的工作,这可以大大提高算法的性能。

总结:结合动态规划的算法设计步骤来说,钢条切割问题也是遵守其标准的。

第一步先确定最优化解的结构特征:最优切割方案是由第一次切割后得到的两段钢条的最优切割方案组成的,或者是第一次切割后,其右端剩余部分的最优切割方案组成的。

第二步递归定义最优解的值,由上面的分析我们可以得到rn = max(pn,r1+rn-1,r2+rn-2,…,rn-1+r1)和rn = max(pi + rn-i) 两个最优解的公式,其满足求得原问题最优解的条件。

第三步根据得到的求最优解公式,计算出结果。我们用到了两种方法:带备忘的自顶向下递归法和自底向上法(非递归)。

第四步构造出最优解。

 

 

好久没有写博客了,期间发生了一些事扰乱了计划,现在要重新回归算法,为明年的华为算法比赛准备

good luck to me

夜深了,时间不多了

 

转载于:https://www.cnblogs.com/1242118789lr/p/7397850.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值