【DP入门】动态规划初步-几类子序列问题

xiaoxiao2021-02-28  125

动态规划初步—子序列问题,本文包括:最大连续子序列和,最大(长)上升子序列,最大(长)公共子序列

1.最大连续子序列和

找出一维数组中和最大的连续子序列,状态转移方程如下:

sum=max(a[i]+sum,a[i]);

例题:HDU 1003-Max Sum(最大连续子序列和)

注:此题由于要输出和最大序列的起始位置和终止位置,形式与上列公式有所出入。但思想一致。

代码示例:

#include<iostream> #include<cstring> using namespace std; #define MAX 100005 int ar[MAX]; int start[MAX],sum[MAX]; int Fun(int ar[],int n) { int end=0; sum[0]=ar[0],start[0]=0; for(int i=1;i<n;i++) { if(sum[i-1]>=0) { sum[i]=sum[i-1]+ar[i]; start[i]=start[i-1]; } else { sum[i]=ar[i]; start[i]=i; } if(sum[i]>sum[end]) end=i; } return end; } int main() { int t,n; cin>>t; int k=1; while(t--) { cin>>n; for(int i=0;i<n;i++) cin>>ar[i]; int ans=Fun(ar,n); cout<<"Case "<<k++<<":" <<endl; cout<<sum[ans]<<" "<<start[ans]+1<<" "<<ans+1<<endl; if(t!=0) cout<<endl; } return 0; }

2.最大上升子序列(LIS)

找出数组中最长的严格升序序列(可以不连续),状态转移方程如下:

dp[i]=max(dp[i],dp[j]+1)ar[j]<ar[i] dp[i][j]=max(dp[i1][j],dp[i][j1])s1[i1]!=s2[j1]

例题:POJ 1458-Common Subsequence(最大公共子序列)

代码示例:

#include<iostream> #include<cstring> using namespace std; #define MAX 1001 int dp[MAX][MAX]; int LCS(char s1[],char s2[]) //最长公共子序列长 { int len1,len2; len1=strlen(s1); len2=strlen(s2); 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; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } } return dp[len1][len2]; } int main() { char s1[MAX],s2[MAX]; while(cin>>s1>>s2) { memset(dp,0,sizeof(dp)); int ans=LCS(s1,s2); cout<<ans<<endl; } return 0; }
转载请注明原文地址: https://www.6miu.com/read-65580.html

最新回复(0)