• 第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
    请按任意键继续. . .
    

      

  • 相关阅读:
    1.1 创造性和动机
    【普及分享】云计算=/=云主机,阿里云=低价低端
    【大话设计模式】——策略模式
    Android 学习笔记之Bitmap位图的缩放
    Android 学习笔记进阶十二之裁截图片
    Android 学习笔记进阶14之像素操作
    Android 给图片 加边框
    android 图片特效处理之 光晕效果
    android 图片特效处理之 图片叠加
    android 图片特效处理之光晕效果
  • 原文地址:https://www.cnblogs.com/l2017/p/10284323.html
Copyright © 2020-2023  润新知