您的位置:首页 > 其它

uva10605 最大公共子序列转化为最大上升子序列

2016-05-19 11:45 295 查看
题目:在一个n*n的棋盘上,格子标号1~n*n,现在有两个人从1跳到n*n(不走重复点),

            现在要求去掉最少的中间点,使得路径是一样的。

分析:dp,LIS,LCS。问题是求最大公共子序列,数据较大需要O(nlgn)算法。

            发现题目中的数据是不重复的,所以可以转化成最大上升子序列;

            记录序列1中每个元素对应的顺序,将序列2中的元素转化成对应序列1中的顺序标号;

            那么,新构成的序列2中递增的序列即为序列1中的先后顺序,所以求出它的LIS即可。#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

int vis[100100],a[100100];
int main()
{
int t,v;
scanf("%d",&t);
for(v=1;v<=t;v++)
{
int n,p,q;
memset(vis,0,sizeof(vis));
scanf("%d%d%d",&n,&p,&q);
p++;
q++;
int p1,q1;
for(int i=1;i<=p;i++)
{
scanf("%d",&p1);
vis[p1]=i;
}
int len=0;
a[0]=0;
for(int i=1;i<=q;i++)
{
scanf("%d",&q1);
if(vis[q1])
{
int q2=vis[q1];
if(q2>a[len])
a[++len]=q2;
else
{
int high=len;
int rear=1;
while(rear<=high)
{
int mid=(high+rear)/2;
if(a[mid]<q2)
rear=mid+1;
else
high=mid-1;
}
a[rear]=q2;
}
}
}
printf("Case %d: %d\n",v,len);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: