2019 GDUT Winter Training II (背包/基础DP/LIS/LCS/概率DP) G - LCS
HDU - 1159(LCS)
原题传送门
专题传送门
题目大意:
给出两段字符串,求最长的公共字符串 (注意是所有元素重新组成的集合在原集合中的顺序与此无关)
题目分析:
这题属于DP的简单应用(记忆化搜索)
我们这里用两个字符串a,b表示
dp [ i ][ j ]表示的是字符串 a 从 0 到 i 与字符串 b 从 0 到 j 中最长公共自序列的长度。
我们容易得到状态转移方程:
如果a[i]==b[j],那么dp[i][j]=dp[i+1][j-1]+1
如果不等,那么dp[i][j]=max(dp[i+1][j],dp[i][j+1])
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#define maxn 1000+5
using namespace std;
int dp[maxn][maxn];
char s[maxn],t[maxn];
int main(){
while(scanf("%s %s",s,t)!=EOF){
memset(dp,0,sizeof(dp));
int m=strlen(s),n=strlen(t);
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(s[i]==t[j]) dp[i+1][j+1]=dp[i][j]+1;
else dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1]);
}
}
cout<<dp[m][n]<<endl;
}
return 0;
}
2019 GDUT Winter Training II (背包/基础DP/LIS/LCS/概率DP) H - 最少拦截系统
HDU - 1257(LIS)
原题传送门
专题传送门
题目大意:
题意是给你n发导弹的高度,一个系统只能拦截高度非递增的一系列导弹,问最少需要几个系统。
题目分析:
求最长上升子序列:给定排好序的一堆数列中,求其的LIS长度。它的LIS长度就是它非上升子序列的个数。
解题思路:定义dp[i]表示能打掉第i枚导弹时,最少需要的拦截系统数。其实就是LIS的一个应用吧。
dp[i] = max(dp[i],dp[j]+1)
在LIS中,dp[i]定义的是表示以第i个元素为结尾时,最长的递增子序列长度。
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e4;
int dp[maxn];
int a[maxn];
int main()
{
int n;
while(cin >> n) {
for(int i=0; i<n; i++) cin >> a[i];
int ans=0;
for(int i=0;i<n;i++){
dp[i]=1;
for(int j=0;j<i;j++){
if(a[j]<a[i]) dp[i]=max(dp[i],dp[j]+1);
ans=max(ans,dp[i]);
}
}
cout<<ans<<endl;;
}
return 0;
}
}