1、最长回文字串(长度、字串)
class Solution
{
public:
string longestPalindrome(string s)
{
int maxn = 1010;
int dp[maxn][maxn];
int ans = 1; //最大回文子串长度
int start = 0;//最大回文子串起始位置
int len = s.length();
memset(dp, 0, sizeof(dp));//dp数组初始化为0
if(len==0||len==1)
return s;
//边界
for (int i = 0; i < len; i++)
{
dp[i][i] = 1;
if (i < len - 1 && s[i] == s[i + 1])
{
dp[i][i + 1] = 1;
ans = 2;
start = i;
}
}
//状态转移方程
for (int L = 3; L <= len; L++)//先从长度为3的字串搜索,判断是否为回文字串
{
for (int i = 0; (i + L - 1) < len; i++)
{
int j = i + L - 1;回文子串终止位置
if (s[i] == s[j] && dp[i + 1][j - 1] == 1)
{
dp[i][j] = 1;
ans = L;
start = i;
}
}
}
//输出(起始位置为start,长度ans)
return s.substr(start, ans);
}
};
2、最长回文子序列
class Solution {
public:
int longestPalindromeSubseq(string s) {
int maxn = 1010;
int len = s.length();
//状态
int dp[maxn][maxn];//表示最长回文子序列的长度
for (int i = len - 1; i >= 0; i--)
{
dp[i][i] = 1; //边界条件
for (int j = i + 1; j < len; j++)
{
//状态转移方程
if (s[i] == s[j])
{
dp[i][j] = dp[i + 1][j - 1] + 2;
}
else
{
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
}
}
}
//输出dp[0][len - 1]
return dp[0][len - 1];
}
};
3、求回文子串个数
class Solution {
public:
int countSubstrings(string s)
{
int maxn = 1010;
int dp[maxn][maxn];
int cnt = 0; //回文子串个数
int len = s.length();
memset(dp, 0, sizeof(dp));//dp数组初始化为0
if(len == 0)
return 0;
cnt += len;//长度为1的回文子串个数
//边界
for (int i = 0; i < len; i++)
{
dp[i][i] = 1;
if (i < len - 1 && s[i] == s[i + 1])
{
dp[i][i + 1] = 1;
cnt++; //长度为2的回文子串
}
}
//状态转移方程
for (int L = 3; L <= len; L++)//先从长度为3的字串搜索,判断是否为回文字串
{
for (int i = 0; (i + L - 1) < len; i++)
{
int j = i + L - 1;回文子串终止位置
if (s[i] == s[j] && dp[i + 1][j - 1] == 1)
{
dp[i][j] = 1;
cnt++;
}
}
}
//输出
return cnt;
}
};
4、数塔
class Solution {
public:
int nuberTower(int n)
{
int dp[n][n];
int f[n][n];
memset(dp, 0, sizeof(dp));//dp数组初始化为0
//输入数塔
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= i; j++)
{
cout << f[i][j];
}
}
//边界
for (int i = 1; i <= n; i++)
{
dp[n][i] = f[n][i];
}
//状态转移方程
for (int i = n - 1; i >= 1; i--)//先从长度为3的字串搜索,判断是否为回文字串
{
for (int j = 1; j <= i; j++)
{
dp[i][j] = max(dp[i + 1][j], dp[i + 1][j + 1]) + f[i][j];
}
}
//输出
return dp[1][1];
}
};
5、最长公共子序列
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
string s1, s2;
while (cin >> s1 >> s2)
{
int len1 = s1.length(), len2 = s2.length();
vector<vector<int> > dp(len1 + 1, vector<int>(len2 + 1, 0)); //定义一个二维数组记录最长公共子序列的长度
//边界条件
for (int i = 0; i <= len1; i++)
{
dp[i][0] = 0;
}
for (int j = 0; j <= len2; j++)
{
dp[0][j] = 0;
}
//状态转移方程
for (int i = 1; i <= len1; i++)
{
for (int j = 1; j <= len2; j++)
{
if (s1[i] == s2[j])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else
{
dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
}
}
}
//读入从1开始的,故长度加1
cout << dp[len1 + 1][len2 + 1] << endl;;
}
return 0;
}
6、最长公共子串
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
string s1, s2;
while (getline(cin, s1))
{
getline(cin, s2);
string ans = "";
//保证s1是短的字符串
if (s1.length() > s2.length())
{
swap(s1, s2);
}
int len1 = s1.length();
int len2 = s2.length();
//定义一个二维数组并初始化为0,来记录公共字串的长度
vector<vector<int> >dp(len1 + 1, vector<int>(len2 + 1, 0));
int maxlen = 0, start = 0;
for (int i = 1; i <= len1; i++)
{
for (int j = 1; j <= len2; j++)
{
if (s1[i - 1] == s2[j - 1])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
if (dp[i][j] > maxlen)
{
maxlen = dp[i][j];
start = i - maxlen;//最长公共字串的起始位置
}
}
}
}
cout << s1.substr(start, maxlen) << endl;
}
return 0;
}
7、01背包问题
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n, V;
while (cin >> n >> V)
{
int c[100],w[100];
int dp[1000];
//输入参数
for (int i = 0; i < n; i++)
{
cin >> w[i];
}
for (int i = 0; i < n; i++)
{
cin >> c[i];
}
//边界
for (int v = 0; v <= V; v++)
{
dp[v] = 0;
}
for (int i = 1; i <= n; i++)
{
for (int v = V; v >= w[i]; v--)
{
//状态转移方程
dp[v] = max(dp[v], dp[v - w[i] + c[i]]);
}
}
int maxValue = 0;
for (int v = 0; v <= V;v++)
{
if (dp[v] > maxValue)
maxValue = dp[v];
}
cout << maxValue << endl;
}
return 0;
}
8、完全背包问题
9、DAG最长路
10、剪绳子
class Solution {
public:
const int maxn = 1010;
int maxlengthAftercutting(int len)
{
int maxlen = 0;
int dp[maxn] = {0};
//边界
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;
dp[3] = 3;
//状态转移方程
for (int i = 4; i <= len; i++)
{
maxlen = 0;
for (int j = 1; j < i / 2; j++)
{
dp[i] = dp[j] * dp[i - j];
maxlen = max(maxlen, dp[i]);
dp[i] = maxlen;
}
}
//输出
return dp[len];
}
};