题目:在一个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;
}
381

被折叠的 条评论
为什么被折叠?



