一、动态规划递归写法
以斐波那契数列为例
自顶向下!
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;
int dp[maxn]; //并令dp[]==-1 表示还未被计算过
int F(int n)
{
if(n==0||n==1) return 1;
if(dp[n]!=-1) return dp[n];
else
{
dp[n]=F(n-1)+F(n-2);
return dp[n];
}
}
二、动态规划递推写法
以数塔问题为例(算法笔记p427)
此题的核心是要找到递推公式,称为状态转移方程
而动态规划的核心——设计状态和状态转移方程
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;
int f[maxn][maxn],dp[maxn][maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
scanf("%d",&f[i][j]);
}
}
for(int j=1;j<=n;j++)
{
dp[n][j]=f[n][j];
}
for(int i=n-1;i>=1;i--)
{
for(int j=n-1;j>=1;j--)
{
dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+f[i][j];
}
}
printf("%d",dp[1][1]);
return 0;
}
三、最大连续子序列和
给定一个数字序列A1,A2…An,求i,j 使得Ai+…Aj最大,输出这个最大和
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;
int A[maxn],dp[maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&A[i]);
}
dp[0]=A[0];
for(int i=1;i<n;i++)
{
dp[i]=max(A[i],dp[i-1]+A[i]);
}
int max=dp[0];
for(int i=0;i<n;i++)
{
if(dp[i]>max)
{
max=dp[i];
}
}
printf("%d",max);
}
四、最长不下降子序列(LIS)
在一个数字序列中,找到一个最长的子序列(可以不连续),使得这个子序列是不下降(非递减的)
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;
int A[maxn],dp[maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&A[i]);
}
int ans=-1;
fill(dp,dp+n,1);
for(int i=0;i<n;i++)
{
//dp[i]=1;
for(int j=0;j<i;j++)
{
if(A[i]>=A[j]&&dp[j]+1>dp[i])
{
dp[i]=dp[j]+1;
}
}
ans=max(ans,dp[i]);
}
printf("%d",ans);
return 0;
}
五、最长公共子序列 LCS
给定两个字符串A和B,求一个字符串,使得这个字符串是A和B的最长公共部分(子序列可以不连续
#include <bits/stdc++.h>
using namespace std;
const int N = 100;
char A[N], B[N];
int dp[N][N];
int main()
{
gets(A + 1);
gets(B + 1);
int lenA = strlen(A+1);
int lenB = strlen(B+1);
for (int i = 0; i <= lenA; i++)
{
dp[i][0] = 0;
}
for (int j = 0; j <= lenB; j++)
{
dp[0][j] = 0;
}
for (int i = 1; i <= lenA; i++)
{
for (int j = 1; j <= lenB; j++)
{
if (A[i] == B[j])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else
{
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
printf("%d", dp[lenA][lenB]);
}
六、最长回文子串
#include <bits/stdc++.h>
using namespace std;
const int N = 100;
char S[N];
int dp[N][N];
int main()
{
gets(S);
int ans=1;
int len=strlen(S);
memset(dp,0,sizeof(dp));
for(int i=0;i<len;i++)
{
dp[i][i]=1;
if(i<len-1)
{
if(S[i]==S[i+1])
{
dp[i][i+1]=1;
ans=2;
}
}
}
for(int L=3;L<=len;L++)
{
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;
}
else dp[i][j]=0;
}
}
printf("%d",ans);
return 0;
}