1. 程式人生 > >HDU1423 最長公共上升子序列

HDU1423 最長公共上升子序列

int void cst () 離散化 scanf %d 滾動 color

先離散化,然後DP

註意這個解法中,dp[i][j][k]代表a序列中前i個和b序列中前j個數結尾為k或小於k時的最大。

但是由於i是單增(一次1->n),而j反復變化(多次1->m),因此i可以滾動,而j不可以

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
int x[501],y[501],xx[501],yy[501],dp[2][501][1001]; int tmp[1002],cnt,m,n,Max; map<int,int>q; void _lisan() { int i,j; q.clear(); cnt=0; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&x[i]); tmp[i]=x[i]; } scanf(
"%d",&m); for(i=1;i<=m;i++) { scanf("%d",&y[i]); tmp[n+i]=y[i]; } sort(tmp+1,tmp+m+n+1); q[tmp[1]]=++cnt; for(i=2;i<=m+n;i++) if(tmp[i]!=tmp[i-1]) q[tmp[i]]=++cnt; for(i=1;i<=n;i++)xx[i]=q[x[i]];
for(i=1;i<=m;i++)yy[i]=q[y[i]]; memset(dp,0,sizeof(dp)); Max=0; } int main() { int T,i,j,k; cin>>T; while(T--){ _lisan(); for(i=1;i<=n;i++) for(j=1;j<=m;j++) { if(xx[i]==yy[j]){ dp[i%2][j][xx[i]]=max(dp[i%2][j][xx[i]],dp[(i+1)%2][j-1][xx[i]-1]+1); } for(k=0;k<=cnt;k++) { dp[i%2][j][k]=max(dp[i%2][j][k],dp[(i+1)%2][j][k]); dp[i%2][j][k]=max(dp[i%2][j][k],dp[i%2][j][k-1]); dp[i%2][j][k]=max(dp[i%2][j][k],dp[i%2][j-1][k]); } } printf("%d\n",dp[n%2][m][cnt]); if(T)printf("\n"); } return 0; }

HDU1423 最長公共上升子序列