简单的dp 两组数据的最长公共升序子序列,遗憾的要死哟~当时紧张个什么劲呢~
解题思路:
就是要一个回文的升序子序列嘛~ 将原数组倒转,就转化成求两个串的最长公共lis .唯一不同的就是两个串的长度应该是动态的.而根据"如果m是奇数,中间那个人可以任意",那么两个串所对应的去区间就应该是 [1,m] [n,m] ,即当i=m时,j=n-i+1,求出两个串的lis后乘以二即可 例如第一个例子 51,52,51:
i=1:
51
51 52 51
i=2:
51 52
51 52
i=3:
51 52 51
51
源代码:
const int N=300;
int n;
int va[N],vb[N];
void init() {
scanf("%d",&n);
for(int i=1,j=n;i<=n;++i,j--) {
scanf("%d",&va[i]);
vb[j]=va[i];
}
}
void work() {
int dp[N];
memset(dp,0,sizeof(dp));
int ans=0;
for(int i=1;i<=n;++i) {
int k=0;
for(int j=1;j<=n-i+1;++j) {
if(va[i]==vb[j]) {
checkmax(dp[j],dp[k]+1);
}
if(va[i]>vb[j]) {
if(dp[k]<dp[j]) {
k=j;
}
}
//判断这个人是不是中间那个人.如果是中间那个人就不能乘以二.
if(j==(n-i+1)) {
checkmax(ans,dp[j]*2-1);
} else {
checkmax(ans,dp[j]*2);
}
//printf("%d ",dp[j]);
}
//puts("");
}
printf("%d\n",ans);
}
int main() {
memset(va,0,sizeof(va));
memset(vb,0,sizeof(vb));
int t;
scanf("%d",&t);
while(t--) {
init();
work();
}
return 0;
}