《算法导论》15.3 动态规划原理(含有矩阵链问题的改良&&C++代码)

最优子结构

1、用动态规划方法求解最优化问题的第一步就是刻画最优解的结构。如前文所述,如果一个
问题的最优解包含其子问题的最优解我们就称此问题具有最优子结构性质。
2、对于不同问题领域,最优子结构的不同体现在两个方面:
(1)原问题的最优解中涉及多少个子问题
(2)在确定最优解使用哪些子问题时,我们需要考察多少种选择。
3、在动态规划方法中,我们通常自底向上地使用最优子结构。也就是说,首先求得子问题的最
优解,然后求原问题的最优解。在求解原问题过程中,我们需要在涉及的子问题中做出选择,选出能得到原问题最优解的子问题。原问题最优解的代价通常就是子问题最优解的代价再加上由此次选择直接产生的代价。
例如,对于钢条切割问题,我们首先求解子问题,确定长度为i=0,1,… n-1的钢条的最优切割方案,然后利用公式(15.2)确定哪个子问题的解构成长度为n的钢条的最优切割方案。此次选择本身所产生的代价就是公式(15.2)中的pi

重叠子问题

1、递归算法一直都在反复求相同的子问题,那么就说最优化问题具有重叠子问题
2、下图就可以看到查表操作的优势在哪里,不用反复求同一个子问题了。
在这里插入图片描述

重构最优解(优化矩阵链乘法)

MEMORIZED-MATRIX-CHAIN(p)
n = p.length - 1
let m[1...n,1...n] be a new table
for i = 1 to n
	for j = i to n
		m[i,j] = ∞
return LOOKUP-CHAIN(m, p, 1, n)
LOOKUP-CHAIN(m,p,i,j)
if m[i,j] < ∞
	return m[i,j]
if i==j
	m[i,j] = 0
else for k = i to j-1
	q = LOOKUP-CHAIN(m, p, i, k) + LOOKUP-CHAIN(m, p, k+1, j) + pi-1 pk pj
	if q < m[i,j]
		m[i,j] = q
return m[i,j]

C++代码

#include <iostream>
#include <vector>
using namespace std;
int LookUpChain(int(*m)[10], int(*s)[10], vector<int>& v, int i, int j);
int MemorizedMatrixChain(vector<int>&v, int(*m)[10], int(*s)[10])
{
	int n = v.size() - 1;
	for (int i = 1; i <= n; i++) {
		for (int j = i; j <= n; j++) {
			m[i][j] = INT_MAX;
		}
	}
	return LookUpChain(m, s,v, 1, n);
}
int LookUpChain(int(*m)[10] , int(*s)[10],vector<int>& v, int i, int j)
{
	int q;
	if (m[i][j] < INT_MAX) {
		return m[i][j];
	}
	if (i == j) {
		m[i][j] = 0;
	}
	else for (int k = i; k <= j - 1; k++) {
		q = LookUpChain(m, s,v, i, k)+LookUpChain(m,s,v,k+1,j)+v[i-1]*v[k]*v[j];
		if (q < m[i][j]) {
			m[i][j] = q;
			s[i][j] = k;
		}
	}
	return m[i][j];
}
void PrintOptimalParens(int(*s)[10], int i, int j)
{
	if (i == j)
	{
		cout << 'A' << i;
	}
	else {
		cout << "(";
		PrintOptimalParens(s, i, s[i][j]);
		PrintOptimalParens(s, s[i][j] + 1, j);
		cout << ")";
	}
}
int main()
{
	vector<int>v1;
	int n;
	cout << "Please enter the number you want!" << endl;
	cin >> n;
	cout << "Please enter the numbers!" << endl;
	int number;
	for (int i = 0; i < n; i++) {
		cin >> number;
		v1.push_back(number);
	}
	int m[10][10], s[10][10];
	int result = MemorizedMatrixChain(v1,m,s);
	cout << "result:" << result<<endl;
	PrintOptimalParens(s, 1, 6);
	cout << endl;
	return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KeepCoding♪Toby♪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值