第15章动态规划------算法导论

 

15.1钢条切割

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<ctime> 
#include<string>
using namespace std;
int p[1000]{ 0,1,5,8,9,10,17,17,20,24,30 };//钢条价格。长度i的价格为p[i]
int ordinary(int *p, int n)//递归法
{
	if (n == 0)
		return 0;
	else
	{
		int q = -1;
		for (int i = 1; i <= n; ++i)
		{
			q = max(p[i] + ordinary(p, n - i), q);
		}
		return q;
	}
}
int top_down_memory(int *p, int n)//动态规划 带备忘的自顶向下法  与递归法类似,只是结果存储起来了
{
	static int b[1000];
	if (n == 0)
		return 0;
	if (b[n] != 0)
	{
		return b[n];
	}
	else
	{
		int q = -1;
		for (int i = 1; i <= n; ++i)
		{
			q = max(p[i] + top_down_memory(p, n - i), q);
		}
		b[n] = q;
		return q;
	}
}
int bottom_up_method(int *p, int n)//动态规划 自底向上 把子结果都先求出来,再求总结果
{
	static int b[1000];
	for (int i = 1; i <= n; ++i)
	{
		int q = -1;
		for (int j = 1; j <= i; ++j)
		{
			q = max(q, p[j] + b[i - j]);
		}
		b[i] = q;
	}
	return b[n];
}
int bottom_up_method_result(int *p, int n)//动态规划 自底向上 把子结果都先求出来,再求总结果 同时把如何切割求出来
{
	static int b[1000];
	static int s[1000];//切割方案
	for (int i = 1; i <= n; ++i)
	{
		int q = -1;
		int ss = -1;
		for (int j = 1; j <= i; ++j)
		{
			if (q < p[j] + b[i - j])
			{
				q = p[j] + b[i - j];
				ss = j;
			}
		}
		s[i] = ss;
		b[i] = q;
	}
	return b[n];
}
int main()
{
	int n;
	clock_t start;

	while (cin >> n)
	{
		start = clock();
		cout << ordinary(p, n);
		cout << "ordinary:" << double(clock() - start) <<endl;
		start = clock();
		cout << bottom_up_method_result(p, n);
		cout << "bottom_up_method_result:" << double(clock() - start) << endl;
		start = clock();
		cout << top_down_memory(p, n);
		cout << "top_down_memory:" << double(clock() - start) << endl;
	}
}

  结果:前面是结果,后面是函数运行时间

25
73ordinary:4497
73bottom_up_method_result:0
73top_down_memory:1

  

 

15.2矩阵链乘法

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<ctime>
#include<string>
using namespace std;
int p[1000]{ 0, 30,35,15,5,10,20,25,99,65,32,45,79,96,15 };
#define N 14

int ordinary(int *p, int a, int b)//递归法
{
	if (a == b)return 0;
	if (a + 1 == b)return p[a] * p[b] * p[b + 1];
	int min = INT_MAX;
	for (int i = a; i < b; ++i)
	{
		if (min >(ordinary(p, a, i) + ordinary(p, i + 1, b) + p[a] * p[i + 1] * p[b + 1]))
			min = ordinary(p, a, i) + ordinary(p, i + 1, b) + p[a] * p[i + 1] * p[b + 1];
	}
	return min;
}
int top_down_memory(int *p, int a, int b)//动态规划 带备忘的自顶向下法  与递归法类似,只是结果存储起来了
{
	static int dd[1000][1000];
	if (dd[a][b])return dd[a][b];
	if (a == b)return 0;
	if (a + 1 == b)return p[a] * p[b] * p[b + 1];
	int min = INT_MAX;
	for (int i = a; i < b; ++i)
	{

		if (min >(top_down_memory(p, a, i) + top_down_memory(p, i + 1, b) + p[a] * p[i + 1] * p[b + 1]))
			min = top_down_memory(p, a, i) + top_down_memory(p, i + 1, b) + p[a] * p[i + 1] * p[b + 1];
	}
	dd[a][b] = min;
	return min;
}
static int s[1000][1000];
int bottom_up_method(int *p, int a, int b)//动态规划 自底向上 把子结果都先求出来,再求总结果
{
	static int q[1000][1000];
	for (int i = 2; i <= b; ++i)
		for (int j = 1; j <= b - i + 1; ++j)
		{
			for (int k = 1; k < i; ++k)
			{
				if (q[j][i] != 0 && q[j][i] > q[j][k] + q[j + k][i - k] + p[j] * p[j + k] * p[i + j])
				{
					q[j][i] = q[j][k] + q[j + k][i - k] + p[j] * p[j + k] * p[i + j];
					s[j][i + j - 1] = k + j - 1;
				}
				if (q[j][i] == 0)
				{
					q[j][i] = q[j][k] + q[j + k][i - k] + p[j] * p[j + k] * p[i + j];
					s[j][i + j - 1] = k + j - 1;
				}
			}
		}

	return q[1][b];
}
void print_result(int s[][1000], int i, int j)
{
	if (i == j)
		cout << "A" << i;
	else
	{
		cout << "(";
		print_result(s, i, s[i][j]);
		print_result(s, s[i][j] + 1, j);
		cout << ")";
	}
}
int main()
{
	int n=N;
	clock_t start;
	start = clock();
	cout << ordinary(p, 1, n-1);//递归法;
	cout << "ordinary:" << double(clock() - start) << " " << endl;
	start = clock();
	cout << top_down_memory(p, 1, n - 1) ;
	cout << "top_down_memory:" << double(clock() - start) << " " << endl;
	start = clock();
	cout << bottom_up_method(p, 1, n - 1) ;
	cout << "bottom_up_method:" << double(clock() - start) << " " << endl;
	start = clock();
	print_result(s, 1, n - 1);
	cout << endl;

	return 0;
}

  结果:前面是结果,后面是函数运行时间

138670ordinary:406
138670top_down_memory:1
138670bottom_up_method:0
((A1(A2A3))(((((((((A4A5)A6)A7)A8)A9)A10)A11)A12)A13))
请按任意键继续. . .

  

 

15.4最长公共子序列

#include<iostream>
#include<vector>
#include<set>
#include<string>
#include<ctime>
#include<algorithm>
using namespace std;

void subset2(const char *a, int n, vector<string> &sub2, string temp = string(), int t = 0)//产生子串,上一篇文章有介绍
{
	if (t == n)
	{
		sub2.push_back(temp);
		return;
	}
	subset2(a, n, sub2, temp, t + 1);
	temp += (a[t]);
	subset2(a, n, sub2, temp, t + 1);
}
int violence(string a, string b)//暴力子串匹配
{
	vector<string> sub2;
	subset2(a.c_str(), a.size(), sub2);
	int max_s = 0;
	for (int i = 0; i < sub2.size(); ++i)
	{
		int k = 0;
		for (int j = 0; j < b.size() && k < sub2[i].size(); ++j)
		{
			if (b[j] == sub2[i][k])
				++k;
		}
		if (k == sub2[i].size())
			max_s = max(max_s, k);
	}
	return max_s;
}

int ordinary(string a, string b, int ii, int jj)//递归法
{
	if (ii == 0 || jj == 0)return 0;
	if (a[ii] == b[jj])
	{
		return ordinary(a, b, ii - 1, jj - 1) + 1;
	}
	return max(ordinary(a, b, ii, jj - 1), ordinary(a, b, ii - 1, jj));
}
int top_down_memory(string a, string b, int ii, int jj)//动态规划 带备忘的自顶向下法  与递归法类似,只是结果存储起来了
{
	static int p[1000][1000];
	if (p[ii][jj])return p[ii][jj];
	if (ii == 0 || jj == 0)return 0;
	if (a[ii] == b[jj])
	{
		p[ii][jj] = top_down_memory(a, b, ii - 1, jj - 1) + 1;
		return p[ii][jj];
	}
	p[ii][jj] = max(top_down_memory(a, b, ii, jj - 1), top_down_memory(a, b, ii - 1, jj));
	return p[ii][jj];
}
int bottom_up_method(string a, string b)//动态规划 自底向上 把子结果都先求出来,再求总结果
{
	int **p = new int *[a.size() + 1];
	for (int i = 0; i < a.size() + 1; ++i)
		p[i] = new int[b.size() + 1];
	for (int i = 0; i < a.size() + 1; ++i)
		for (int j = 0; j < b.size() + 1; ++j)
			p[i][j] = 0;
	for (int i = 0; i < a.size(); ++i)
		for (int j = 0; j < b.size(); ++j)
		{
			if (a[i] == b[j])
				p[i + 1][j + 1] = p[i][j] + 1;
			else
				p[i + 1][j + 1] = max(p[i][j + 1], p[i + 1][j]);
		}
	//for (int i = 0; i < a.size() + 1; ++i)
	//{
	//	for (int j = 0; j < b.size() + 1; ++j)
	//		cout<<p[i][j]<<" ";
	//	cout << endl;
	//}
	return p[a.size()][b.size()];
}



int main()
{
	string a, b;
	clock_t start;

	cin >> a >> b;

	start = clock();

	cout << violence(a, b);
	cout << "violence:" << double(clock() - start) << " " << endl;
	start = clock();
	cout << bottom_up_method(a, b);
	cout << "bottom_up_method:" << double(clock() - start) << " " << endl;
	start = clock();
	cout << ordinary(a, b, a.size(), b.size());
	cout << "ordinary:" << double(clock() - start) << " " << endl;
	start = clock();
	cout << top_down_memory(a, b, a.size(), b.size());
	cout << "top_down_memory:" << double(clock() - start) << " " << endl;
	start = clock();

}

  结果:前面是结果,后面是函数运行时间

{1,3,4,5,6,7,7,8}
{3,5,7,4,8,6,7,8,2}
12violence:4400
12bottom_up_method:1
12ordinary:5798
12top_down_memory:7
请按任意键继续. . .

  

 

转载于:https://www.cnblogs.com/l2017/p/10284323.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值