UVA10635 Prince and Princess(LIS)

题意:王子和公主同时从1出发走到 n*n, 求他们两个路径的最长公共子序列;

思路:因为这题n有250,如果用LCS负责度为O(n^2),容易超时,于是我们选择它的优化版Lis算法来求最长公共子序列,这样我们的复杂度就降为O(n*logn)了。

Lis算法:

先回顾经典的O(n^2)的动态规划算法,设A[t]表示序列中的第t个数,F[t]表示从1到t这一段中以t结尾的最长上升子序列的长度,初始时设F[t]
= 0(t = 1, 2, ..., len(A))。则有动态规划方程:F[t] = max{1, F[j] + 1} (j = 1, 2, ..., t - 1, 且A[j] < A[t])。

  现在,我们仔细考虑计算F[t]时的情况。假设有两个元素A[x]和A[y],满足

  (1)x < y < t (2)A[x] < A[y] < A[t] (3)F[x] = F[y]

  此时,选择F[x]和选择F[y]都可以得到同样的F[t]值,那么,在最长上升子序列的这个位置中,应该选择A[x]还是应该选择A[y]呢?

  很明显,选择A[x]比选择A[y]要好。因为由于条件(2),在A[x+1] ... A[t-1]这一段中,如果存在A[z],A[x] < A[z] < a[y],则与选择A[y]相比,将会得到更长的上升子序列。

  再根据条件(3),我们会得到一个启示:根据F[]的值进行分类。对于F[]的每一个取值k,我们只需要保留满足F[t] = k的所有A[t]中的最小值。设D[k]记录这个值,即D[k] = min{A[t]} (F[t] = k)。

  注意到D[]的两个特点:

  (1) D[k]的值是在整个计算过程中是单调不上升的。

  (2) D[]的值是有序的,即D[1] < D[2] < D[3] < ... < D[n]。

  利用D[],我们可以得到另外一种计算最长上升子序列长度的方法。设当前已经求出的最长上升子序列长度为len。先判断A[t]与D[len]。若A[t] > D[len],则将A[t]接在D[len]后将得到一个更长的上升子序列,len = len + 1, D[len] = A[t];否则,在D[1]..D[len]中,找到最大的j,满足D[j]
< A[t]。令k = j + 1,则有D[j] < A[t] <= D[k],将A[t]接在D[j]后将得到一个更长的上升子序列,同时更新D[k] = A[t]。最后,len即为所要求的最长上升子序列的长度。

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=250*250+10;
int n, p, q, a;
int prince[maxn], princess[maxn];
int arr[maxn];

int Lis(int n)
{
	int len=0;
	memset(arr, 0, sizeof(arr));
	for(int i=1; i<=n; i++)
	{
		int l=1, r=len;
		while(l<=r)
		{
			int mid=(l+r)>>1;
			if(prince[i]>arr[mid])
				l=mid+1;
			else r=mid-1;
		}
		arr[l]=prince[i];
		if(l>len)
			len=l;
	}
	return len;
}

int main()
{
	int t=0;
	scanf("%d", &t);
	int cas=1;
	while(t--)
	{
		scanf("%d%d%d", &n, &p, &q);
		memset(prince, 0, sizeof(prince));
		memset(princess, 0, sizeof(princess));
		p++, q++;
		for(int i=1; i<=p; i++)
		{
			scanf("%d", &prince[i]);
		}
		for(int i=1; i<=q; i++)
		{
			scanf("%d", &a);
			princess[a]=i;
		}
		for(int i=1; i<=p; i++)
		{
			prince[i]=princess[prince[i]];
		}
		printf("Case %d: %d\n", cas, Lis(p));
		cas++;
	}
	return 0;
}
时间: 2024-08-02 14:52:36

UVA10635 Prince and Princess(LIS)的相关文章

uva 10635 Prince and Princess(DP)

uva 10635 Prince and Princess(DP) In an n x n chessboard, Prince and Princess plays a game. The squares in the chessboard are numbered 1, 2, 3 ... n*n, as shown below: Prince stands in square 1, make p jumps and finally reach square n*n. He enters a

uva 10635 Prince and Princess(LCS问题转化成LIS问题O(nlogn))

题目大意:有两个长度分别为p+1和q+1的序列,每个序列中的各个元素互不相同,且都是1~n^2之间的整数.两个序列的第一个元素均为1.求出A和B的最长公共子序列长度. 分析:本题是LCS问题,但是p*q<=62500,O(pq)的算法显然会LE.在这里有一个条件,每个序列中的各个元素互不相同,所以可以把A中元素重新编号为1~p+1.例如,样例中A={1,7,5,4,8,3,9},B={1,4,3,5,6,2,8,9},因此把A重新编号为{1,2,3,4,5,6,7},则B就是{1,4,6,3,0

uva10635 Prince and Princess LCS 变 lIS

// uva10635 Prince and Princess LCS 变 lIS // 本意求LCS,但是规模有60000多,复杂度肯定不够 // 注意如果俩个序列的值的范围相同,那么可以在一个 // 串中记录在另外一个串中的位置.这样就可以转化成 // 最长上升子序列的问题啦,复杂度是nlogn,可以ac // 这题,还是挺有考究的价值的,很不错 // 哎,继续练吧..... #include <algorithm> #include <bitset> #include <

Gym 101246H ``North-East&#39;&#39;(LIS)

http://codeforces.com/gym/101246/problem/H 题意: 给出n个点的坐标,现在有一个乐队,他可以从任一点出发,但是只能往右上方走(包括右方和上方),要经过尽量多的点.输出它可能经过的点和一定会经过的点. 思路: 分析一下第一个案例,在坐标图上画出来,可以发现,他最多可以经过4个点,有两种方法可以走. 观察一下,就可以发现这道题目就是要我们求一个LIS. 首先,对输入数据排一下顺序,x小的排前,相等时则将y大的优先排前面. 用二分法求LIS,这样在d数组中就可

UVA - 10534Wavio Sequence(LIS)

题目:UVA - 10534Wavio Sequence(LIS) 题目大意:给出N个数字,找出这样的序列:2 * n + 1个数字组成.前面的n + 1个数字单调递增,后面n + 1单调递减. 解题思路:从前往后找一遍LIS,再从后往前找一遍LIS.最后只要i这个位置的LIS的长度和LDS的长度取最小值.再*2 - 1就是这个波浪数字的长度.注意这里的求LIS要用nlog(n)的算法,而且这里的波浪数字的对称并不是要求i的LIS == LDS,而是只要求LIS和LDS最短的长度就行了,长的那个

uva10723 - Cyborg Genes(LIS)

题目:uva10723 - Cyborg Genes(LIS) 题目大意:给出两个字符串,要求的到一个新的字符串,它保持了两个字符串的字符的特征,也就是可以在这个字符串中找到前两个字符串的子序列,求这样的字符串的最短长度和有多少种这样的不同的字符串. 解题思路:LIS.首先先要找出最长的公共子序列,这样得到的新的字符串的长度才会是最小:l1 + l2 - l[1][N]: l[i][j] :第一个字符串的前i个字符和第二个字符串的前j个字符的最长的公共子序列长度. n[i][j]: 使得第一个字

hoj_10001_朴素DP(LIS)

Longest Ordered Subsequence Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KB Total submit users: 1937, Accepted users: 1621 Problem 10001 : No special judgement Problem description A numeric sequence of ai is ordered if a1 < a2 <

最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)

最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj.例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列. 考虑最长公共子序列问题如何分解成

poj 3903 &amp; poj 2533 最长上升子序列(LIS)

最长上升子序列. 做这道题之前先做了2533,再看这道题,感觉两道题就一模一样,于是用2533的代码直接交, TLE了: 回头一看,数据范围.2533 N:0~1000:3903 N :1~100000. 原因终归于算法时间复杂度. 也借这道题学习了nlgn的最长上升子序列.(学习链接:http://blog.csdn.net/dangwenliang/article/details/5728363) 下面简单介绍n^2 和 nlgn 的两种算法. n^2: 主要思想:DP: 假设A1,A2..