zoukankan      html  css  js  c++  java
  • 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;
    }


  • 相关阅读:
    我的第一篇博客
    文献笔记5
    文献笔记4
    文献笔记8
    文献笔记6
    文献笔记10
    文献笔记7
    文献笔记1
    文献笔记2
    文献笔记3
  • 原文地址:https://www.cnblogs.com/wolf940509/p/6617129.html
Copyright © 2011-2022 走看看