码迷,mamicode.com
首页 > Windows程序 > 详细

CF10D LCIS&&Acwing 272

时间:2019-09-03 22:18:08      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:read   lis   ios   i++   turn   sig   oid   using   ++   

一道经典\(DP\)

LCS

\[ f[i][j]=f[i-1][j-1]+1\;(i,j>0,a[i]=b[j])\]
\[ f[i][j]=max(f[i][j-1],f[i-1][j])\;(i,j>0,a[i]\not=b[j])\]

其中,f[i][j]a序列前i个元素与b序列前j个元素的\(LCS\)长度

LIS

\[f[i]=max~f[j]+1~(j<i,a[j]<a[i])\]

f[i]为以第i个元素结尾的\(LIS\)长度。

LCIS

我们想办法糅合这两种动态规划的思想,设f[i][j]代表的是a序列前i个元素与b序列前j个元素的\(LCIS\)长度(最长公共上升子序列),t为最长\(LCIS\)的结尾元素位置,我们可以推出状态转移方程

\[f[i][j]=f[i-1][j]~(a[i]\not=b[j])\]

\[f[i][j]=max(f[i-1][j],f[i-1][t]+1)~(a[i]=b[j])\]

最后,再转移时储存位置,输出

Code One

二维

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<string>
#define ll long long
#define maxn 550
#define inf 2147483647
#define mod 10003
#define eps 1e-6
#define pi acos(-1.0)
#define de(x) ((x)*(x))
using namespace std; 
inline int read(){
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int n,a[maxn],b[maxn],f[maxn][maxn],g[maxn][maxn];
inline void put(int x){
    if(!x) return;
    put(g[n][x]);
    printf("%d ",b[x]); 
}
signed main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    int m=read(),p=0;
    for(int i=1;i<=m;i++) b[i]=read();
    for(int i=1,t=0;i<=n;++i,t=0)
    for(int j=1;j<=m;++j){
        f[i][j]=f[i-1][j];      
        g[i][j]=g[i-1][j];
        if(a[i]==b[j]&&f[i-1][t]+1>f[i][j]){
            f[i][j]=f[i-1][t]+1;
            g[i][j]=t;  
        }
        if(b[j]<a[i]&&f[i-1][j]>f[i-1][t]) t=j;
        //检查t是否为最长LCIS的结尾元素位置
    }
    for(int i=1;i<=m;i++) 
    if(f[n][i]>f[n][p]) p=i;
    printf("%d\n",f[n][p]);
    put(p);
    return 0;
}

优化

分析状态转移方程可知f[i][j]都是由f[i-1][j]得来的,因此可以优化空间,设f[i]代表的是a序列前i个元素与b序列的LCIS长度,t为最长LCIS的结尾元素位置,新的状态转移方程为

\[f[i]=f[t]+1~(a[i]=b[j])\]

Code Two

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<string>
#define ll long long
#define maxn 550
#define inf 2147483647
#define mod 10003
#define eps 1e-6
#define pi acos(-1.0)
#define de(x) ((x)*(x))
using namespace std; 
inline int read(){
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int n,a[maxn],b[maxn],f[maxn],g[maxn];
inline void put(int x){
    if(!x) return;
    put(g[x]);
    printf("%d ",b[x]); 
}
signed main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    int m=read(),p=0;
    for(int i=1;i<=m;i++) b[i]=read();
    for(int i=1,t=0;i<=n;++i,t=0)
    for(int j=1;j<=m;++j){
        if(a[i]==b[j]){
            f[j]=f[t]+1;
            g[j]=t;  
        }
        if(b[j]<a[i]&&f[j]>f[t]) t=j;
    }
    for(int i=1;i<=m;i++) 
    if(f[i]>f[p]) p=i;
    printf("%d\n",f[p]);
    put(p);
    return 0;
}

技术图片

效果显著

\(P.S\)可以写写Acwing 272

CF10D LCIS&&Acwing 272

标签:read   lis   ios   i++   turn   sig   oid   using   ++   

原文地址:https://www.cnblogs.com/cbyyc/p/11455793.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!