HDU 4512 吉哥系列故事——完美队形I LCIS 最长递增公共子序列
http://acm.hdu.edu.cn/showproblem.php?pid=4512
题意:
给你一个序列,找出回文串,可以不连续的,但必须满足从前面到中间是递增的,中间到结尾时递减的。
如果没有中间的话,也就是回文串是偶数,则中间两个必须相等。
坑爹:
本想直接将序列反过来然后和原串做LCIS找到一个最长的序列,但是有个恶心的数据一下子没想到,结果
WA了好久, 3 1 2 1 3 这组数据,如果反过来的话他们的LCIS值会是3,但根据题意是不对的。
解法:
原本的模板是两个for,都是1~N循环,但这样就会出现上述问题,所以在里层循环范围改成 j<(N-i+1),因为
N-i+1是 i 的对称点,但对应反过来的那个数组来说就是相同的点了,这个就是一个边界,因为超过了这个边界就不能
搜了,因为这不是两个字符串,这是强行将一个字符串转换为两个,计算的时候不能同时用到一块去,从 N-i+1到
N其实就是原串的1到i ,因为不能共用所以这里就是边界了。
回文串是否为奇偶的问题只用判断在搜到的点是不是相对原串的同一位置,如果是的话就代表这个回文串为奇数,
否则为偶数。
1 #include<iostream> 2 using namespace std; 3 4 const int maxn = 200 + 10; 5 int str[maxn]; 6 int str2[maxn]; 7 int DP[maxn]; 8 int N; 9 10 int MAX(int a,int b) 11 { 12 return a > b ? a : b; 13 } 14 15 int LCIS() 16 { 17 memset(DP,0,sizeof(DP)); 18 int i; 19 int j; 20 int max; 21 int ans = 1; 22 for(i=1; i<=N; i++) 23 { 24 max = 0; 25 for(j=1; j<=(N-i+1); j++) 26 { 27 if(str[i] > str2[j] && max < DP[j]) 28 { 29 max = DP[j]; 30 } 31 if(str[i] == str2[j]) 32 { 33 DP[j] = max + 1; 34 } 35 if(i < (N - j + 1)) 36 { 37 ans = MAX(ans, DP[j]*2); 38 } 39 else 40 { 41 ans = MAX(ans, DP[j]*2-1); 42 } 43 } 44 } 45 return ans; 46 } 47 48 int main() 49 { 50 int T; 51 scanf("%d",&T); 52 while(T--) 53 { 54 scanf("%d",&N); 55 int i; 56 for(i=1; i<=N; i++) 57 { 58 scanf("%d",&str[i]); 59 str2[N-i+1] = str[i]; 60 } 61 int ans = LCIS(); 62 printf("%d\n",ans); 63 } 64 return 0; 65 }