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 }

 

 

 

 

posted @ 2012-10-05 10:13  proverbs  阅读(738)  评论(0编辑  收藏  举报