动态规划
采用动态规划求解的问题需要具有两个特性:
- 最优子结构(Optimal Substructure):问题的一个最优解中所包含的子问题的解也是最优的。
-
重叠子问题(Overlapping Subproblems):用递归算法对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。
综上所述,动态规划的关键是 —— 记忆,空间换时间,不重复求解,从较小问题解逐步决策,构造较大问题的解。
1、动态规划一般可分为线性规划、区域规划、树形规划、背包动态规划四类。
2、动态规划两个重要概念:状态和状态转移方程。
3、最长公共子串、最长公共子序列、最长递增子序列。
最长公共子串与最长公共子序列的区别:子串要求在原字符串中是连续的,而子序列则只需保持相对顺序,并不要求连续。
最长公共子序列(LSC)
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
int array[2000][2000];
int dp[2000][2000];
int main()
{
//有两条随机序列,如 1 3 4 5 5 6 和 2 4 5 5 7 6,则它们的最长公共子序列便是:4 5 5 6,最长公共子串为4 5 5。
string str1, str2;
memset(dp, 0, sizeof(dp));
while (cin >> str1 >> str2)
{
int la = str1.length();//字符串1的长度
int lb = str2.length();//字符串2的长度
for (int idx = 1; idx <= la; idx++)
{
for (int jdx = 1; jdx <= lb; jdx++)
{
if (str1[idx-1] == str2[jdx-1])//两个字符串中有相同的字符
{
dp[idx][jdx] = dp[idx - 1][jdx - 1] + 1;
}
else
dp[idx][jdx] = max(dp[idx - 1][jdx], dp[idx][jdx - 1]);
}
}
cout << dp[la][lb] << endl;//统计子字符序列的个数
}
system("pause");
return 0;
}
最长公共子串
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
int array[2000][2000];
int dp[2000][2000];
int main()
{
string str1, str2;
memset(dp, 0, sizeof(dp));
while (cin >> str1 >> str2)
{
int biggest = 0;
int la = str1.length();//字符串1的长度
int lb = str2.length();//字符串2的长度
for (int idx = 1; idx <= la; idx++)
{
for (int jdx = 1; jdx <= lb; jdx++)
{
if (str1[idx-1] == str2[jdx-1])//两个字符串中有相同的字符
{
dp[idx][jdx] = dp[idx - 1][jdx - 1] + 1;
if (dp[idx][jdx] > biggest)
biggest = dp[idx][jdx];
}
else
dp[idx][jdx] = 0;
}
}
cout << biggest << endl;//统计子串序列的个数
}
system("pause");
return 0;
}
最长递增子序列(LIC)
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
int main()
{
int n = 0;
int dp[1000];//存放子序列中数字的个数
int arr[1000];//序列
while (cin >> n)
{
int res = 0;
memset(arr, 0, sizeof(arr));
memset(dp, 0, sizeof(dp));
for (int idx = 0; idx < n; idx++)
cin >> arr[idx];
for (int idx = 0; idx < n; idx++)
{
dp[idx] = 1;
for (int jdx = 0; jdx < idx; jdx++)
{
if (arr[idx] > arr[jdx])
dp[idx] = max(dp[idx], dp[jdx] + 1);
}
res = max(res, dp[idx]);
}
cout << res << endl;
}
return 0;
}
最长递增子串
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int main()
{
//最长递增子串
int n = 0;
int arr[1000];//序列
queue<int> q;
while (cin >> n)
{
int res = 0;
int count = 1;
memset(arr, 0, sizeof(arr));
for (int idx = 0; idx < n; idx++)
{
cin >> arr[idx];
q.push(arr[idx]);
}
while (!q.empty())
{
int temp = q.front();
q.pop();
if (q.size() && temp < q.front())
count++;
else
count = 1;
res = max(res, count);
}
cout << res << endl;
}
system("pause");
return 0;
}