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