DP专辑之最长公共子序列及其变形

vijos1111(裸的最长公共子序列)

链接:www.vijos.org/p/1111

题解:好久没有写最长公共子序列了,这题就当是复习了。求出最长公共子序列,然后用两个单词的总长度减去最长公共子序列

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=101;
int dp[maxn][maxn];
char a[maxn],b[maxn];
int main()
{
	while(cin>>a>>b)
	{
		int n=strlen(a);
		int m=strlen(b);
		for(int i=0;i<n;i++)     //最长公共子序列模板 
		for(int j=0;j<m;j++)
		{
			if(a[i]==b[j])
			dp[i+1][j+1]=dp[i][j]+1;
			else
			dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
		}
		cout<<n+m-dp[n][m]<<endl;
	}
	return 0;
}

vijos1680(最长公共子序列的变形)

链接:www.vijos.org/p/1680

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=2001;
int dp[maxn][maxn];
char a[maxn],b[maxn];
int minx(int x,int y,int z)
{
    int ab=x;
    if(y<ab)   ab=y;
    if(z<ab)    ab=z;
    return ab;
}
int main()
{
    int k;
    while(cin>>a>>b>>k)
    {
        int n=strlen(a);
        int m=strlen(b);
        for(int i=0;i<n;i++)
            dp[i+1][0]=dp[i][0]+k;
        for(int i=0;i<m;i++)
            dp[0][i+1]=dp[0][i]+k;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            dp[i+1][j+1]=minx(dp[i][j+1]+k,dp[i+1][j]+k,dp[i][j]+abs(a[i]-b[j]));
        cout<<dp[n][m]<<endl;
    }
    return 0;
}

vijos 1264(最长公共上升序列)

链接:www.vijos.org/p/1264

题解:用dp[i,j]表示a序列的前i个为结尾和以b序列的第j个为结尾的最长上升公共序列长度。则:

dp[i,j]=max{dp[i-1,k]}+1 | (a[i]=b[j]) and (b[k]<b[j])
dp[i,j]=dp[i-1,j] | (a[i]<>b[j])

程序里面在j循环顺带着就找到了最小的k。对于所有小于a[i]的b[k],必定在a[i]=b[j]时小于b[j],所以满足了约束条件。
最后再把i那维给降调。(为什么没有滚动,因为b[k]<>a[i],所dp[k]必定没有没修改)


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=501;
int dp[maxn];
int a[maxn],b[maxn];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,m;
		cin>>n;
		for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
		cin>>m;
		for(int i=1;i<=m;i++)
		scanf("%d",&b[i]);
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;i++)   //最长上升公共序列 
		{
			int mx=0;
			for(int j=1;j<=m;j++)
			{
				if(a[i]>b[j])
				mx=max(mx,dp[j]);
				else if(a[i]==b[j])
				dp[j]=max(mx+1,dp[j]);
			}
		}
		int mx=0;
		for(int i=1;i<=m;i++)
		if(mx<dp[i])
		mx=dp[i];
		cout<<mx<<endl;
	}
	return 0;
}


posted @ 2014-05-13 21:42  wolf940509  阅读(168)  评论(0编辑  收藏  举报