POJ 2127 DP(n^2)

题意:

最长公共上升子序列

 

思路:

以前都是写的n^3的,今天听说有n^2算法,就看了一下。其实就是n^3的优化

以前n^3的方程是:

dp[i][j]表示以a串的前i个数字且以b[j]结尾的的最大的LCIS的长度

转移是:

dp[i][j]=max(dp[i][j],dp[i-1][k]+1)    a[i]==b[j]&&b[k]<b[j]   1<=k<j

dp[i][j]=max(dp[i][j],dp[i-1][j])     a[i]!=b[j]

 

现在开始优化:

第一个方程是n^3的,i,j两层循环是肯定干不掉的,那我们就想办法干掉k的这层循环

可以观察发现循环i层的状态是由i-1层转移过来的,这样就暗示我们要优化循环顺序,i的循环在外部,j的循环在内部

这样我们才可以降低复杂度:

考虑以下不等式:

a[i]==b[j]>b[k]    ------>    a[i]>b[k]

(仔细想想上面的不等式能给你启发)

 

那么!这个东西可以再上一层循环中求出来!发现没有?

在进入内层循环时,就可以维护一个最大值ma;

当b[j]<a[i]时,ma=max(ma, dp[i-1][ j])

当出现b[j]==a[i]时,就可以直接取dp[i][j]=ma+1

(说白了,就是把k的循环用j充当了。)

 

View Code
 1 #include <cstdio>

 2 #include <cstring>

 3 #include <cstdlib>

 4 #include <string>

 5 #include <iostream>

 6 

 7 #define N 600

 8 

 9 using namespace std;

10 

11 int n,m,a[N],b[N],dp[N][N],pre[N][N],stk[N];

12 

13 void go()

14 {

15     for(int i=1;i<=n;i++) scanf("%d",&a[i]);

16     scanf("%d",&m);

17     for(int j=1;j<=m;j++) scanf("%d",&b[j]);

18     memset(dp,0,sizeof dp);

19     dp[0][0]=0;

20     for(int i=1,ma,last;i<=n;i++)

21     {

22         ma=0;last=0;

23         for(int j=1;j<=m;j++)

24         {

25             if(a[i]==b[j])

26             {

27                 dp[i][j]=ma+1;

28                 pre[i][j]=last;

29             }

30             else dp[i][j]=max(dp[i][j],dp[i-1][j]);

31             if(b[j]<a[i]&&ma<dp[i-1][j])

32             {

33                 ma=dp[i-1][j];

34                 last=j;

35             }

36         }

37     }

38     int ans=-1,x=n,y,p=0;

39     for(int j=1;j<=n;j++)

40         for(int i=1;i<=m;i++)

41             if(ans<dp[j][i])

42             {

43                 ans=dp[j][i];

44                 y=i;

45             }

46     printf("%d\n",ans);

47     

48     while(ans--)

49     {

50         stk[++p]=b[y];

51         while(a[x]!=b[y]) x--;

52         y=pre[x][y];

53         x--;

54     }

55     for(int i=p;i>=1;i--) printf("%d ",stk[i]);

56 }

57 

58 int main()

59 {

60     while(scanf("%d",&n)!=EOF) go();

61     return 0;

62 }

 

 

 

 

你可能感兴趣的:(poj)