友好城市(二分查找)【DP】

> Description
Palmia国有一条横贯东西的大河,河有笔直的南北两岸,岸上各有位置各不相同的N个城市。北岸的每个城市有且仅有一个友好城市在南岸,而且不同城市的友好城市不相同。
每对友好城市都向政府申请在河上开辟一条航线连接两个城市,但是由于河上经常起大雾,政府决定避免任意两条航线交叉,以避免事故。请编程帮助政府做出一些批准和拒绝申请的决定,使得在保证任意两条航线不相交的情况下,被批准的申请尽量多。


> Input
第1行,一个整数N(1<=N<=5000),表示城市数。
第2行到第n+1行,每行两个整数,分别表示南岸和北岸的一对友好城市的坐标。(0<=xi<=10000)


> Output
一行,输出一个整数,表示政府所能批准的最多申请数。


> Sample Input
7
22 4
2 6
10 3
15 12
9 8
17 17
4 2


> Sample Output
4


> 解题思路
这一道题表示调试了超级久。。。
输入中有两个数据a和b,我用a把它二分排序一下,b跟着自己的友好城市(也就是a)排。然后再根据b弄一个最长不下降序列求最长不下降序列就行了。


> 代码

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=5001;
int f[maxn],a[maxn],b[maxn],n,ans=0;

void ooo(int x,int y)
{
	int a1=a[y],b1=b[y];
	for(int i=y;i>=x+1;i--)
	{
		a[i]=a[i-1]; b[i]=b[i-1];
	}
	a[x]=a1; b[x]=b1;
}//调换位置不是简单的两数之间调换,把它插入以后,后面全部向后移

int ooo1(int x)
{
	int r=0,l=x,mid;
    do
	{
		mid=(r+l)/2;
		if(a[mid]<a[x]) r=mid+1;
		 else l=mid-1;
	}while(r<=l);
	return r;
}//二分查找

int main()
{
	int s;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i],&b[i]);
        s=ooo1(i);
		if(s!=i) ooo(s,i);
		//当查找到的位置不是它现在的位置就把它调换位置
    }   
	for(int i=n;i>=1;i--)
	{
		for(int j=n;j>i;j--)
		 if(b[j]>b[i]) f[i]=max(f[i],f[j]);
		f[i]++;//求最长不下降序列
		ans=max(f[i],ans);
	}
	printf("%d",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43010386/article/details/82943568