一、动态规划的思想:
将待求解问题分解为若干子问题,先求解这些子问题的解,再结合子问题的解得到原问题的解。
用一个表记录所有已解决的子问题的答案,不管该子问题以后是否被用到,只要它被计算过,就将结果填入表中。
二、与分治的区别:
适用于动态规划法求解的问题经分解得到的子问题往往不是相互独立的。若用分治法来解这类问题,则分解得到的子问题太多,以至于解决原问题需要耗费指数级时间。
三、求解步骤:
1、找出最优解的性质,并刻画其结构特征
2、递归地定义最优解
3、以自顶向上的方法计算最优值
4、根据计算最优值得到的信息,构造最优解
四、动态规划例题之矩阵连乘问题:
题目描述
一个n*m矩阵由n行m列共n*m个数排列而成。两个矩阵A和B可以相乘当且仅当A的列数等于B的行数。一个N*M的矩阵乘以一个M*P的矩阵等于一个N*P的矩阵,运算量为nmp。
矩阵乘法满足结合律,A*B*C可以表示成(A*B)*C或者是A*(B*C),两者的运算量却不同。例如当A=2*3 B=3*4 C=4*5时,(A*B)*C=64而A*(B*C)=90。显然第一种顺序节省运算量。
现在给出N个矩阵,并输入N+1个数,第i个矩阵是a[i-1]*a[i]
输入
第一行n(n<=100)
第二行n+1个数
输出
最优的运算量
样例输入 Copy
3 2 3 4 5
样例输出 Copy
64
分析题目:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 105;
typedef long long LL;
LL dp[N][N];
LL a[N];
LL solve(int l, int mid, int r)
{
return (LL)a[l] * (LL)a[mid] * (LL)a[r];
}
void unRe(){
int a = 1, b = 2, c = 3, d = 4;
a = b + c * d;
b = a ++ + c - d + c;
}
int main()
{
int n;
cin >> n;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
dp[i][j] = 1e18;
for(int i=1; i<=n+1; i++)
{
cin >> a[i];
dp[i][i] = 0;
}
for(int k=1; k<=n; k++)
for(int i=k; i>=1; i--)
for(int j=k-1; j>=i; j--)
dp[i][k] = min(dp[i][k], dp[i][j]+dp[j+1][k]+a[i]*a[j+1]*a[k+1]);
cout << dp[1][n] << endl;
return 0;
}
五、最长公共子序列
若给定两个序列X,Y,当另一个序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。
例如,若X={A,B,C,B,D,A,B},Y={B,D,C,A,B,A} 则{B,C,A}是一个公共子序列,但不是最长的。
{B,C,B,A}是一个最长的公共子序列。这个不是连续的哦。
题目描述
需要你做的就是写一个程序,得出最长公共子序列。
最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。
输入
第一行给出一个整数N(0<N<100)表示待测数据组数
接下来每组数据两行,分别为待测的两组字符串。每个字符串长度不大于1000.
输出
每组测试数据输出一个整数,表示最长公共子序列长度。每组结果占一行。
样例输入 Copy
2 asdf adfsd 123abc abc123abc
样例输出 Copy
3 6
分析题目:
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
string a,b;
cin>>a>>b;
int m=a.length();
int n=b.length();
int dp[m+1][n+1];
//给边框加0
//给第一行加0
for(int i=0;i<m;i++)
{
dp[0][i]=0;
}
//给第一列加0
for(int i=0;i<n;i++)
{
dp[i][0]=0;
}
//递归
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i-1]==b[j-1])
{
dp[i][j]=1+dp[i-1][j-1];
}
else
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
printf("%d\n",dp[m][n]);
}
return 0;
}