Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
Palmia国有一条横贯东西的大河,河有笔直的南北两岸,岸上各有位置各不相同的N个城市。北岸的每个城市有且仅有一个友好城市在南岸,而且不同城市的友好城市不相同。
每对友好城市都向政府申请在河上开辟一条直线航道连接两个城市,但是由于河上雾太大,政府决定避免任意两条航道交
叉,以避免事故。编程帮助政府做出一些批准和拒绝申请的决定,使得在保证任意两条航线不相交的情况下,被批准的申请尽
量多。
【输入格式】
第1行,一个整数N(1<=N<=5000),表示城市数。
第2行到第n+1行,每行两个整数,中间用1个空格隔开,分别表示南岸和北岸的一对友好城市的坐标。(0<=xi<=10000)
【输出格式】
仅一行,输出一个整数,政府所能批准的最多申请数。
Sample Input
7 22 4 2 6 10 3 15 12 9 8 17 17 4 2
Sample Output
4
【题解】
首先把这些友好城市的信息。按照南岸的序号大小升序排列。
这些信息可以看成线。
假设有i<j;
且j的另外一端为xj,i的另外为xi。如果xi>xj。则这两条线会有交点。
这个时候我们可以把南岸的n个数字看成是1..n;
然后北岸的位置是a[i]的值。
南岸1..n是a数组的下标i
则我们要从1..n中选几个数字。满足
当i<j时a[j] > a[i](如果不满足就会有交点。),然后要使得数字的数目最大。
这就是一个最长不下降子序列的问题了。
设m[i]为以i为序列的最后一个数字的最长不下降子序列的长度。
m[i]初值为1
for (int i = 2;i <= n;i++)
for (int j = 1;j <= i-1;j++)
if(a[i] > a[j] && f[i] < f[j]+1)
f[i] = f[j]+1;
最后在1..n中找最大值f[k]
【代码】
#include <cstdio> #include <algorithm> using namespace std; struct data { int a,b; }; int n,m[5010]; data city[5010]; int cmp(const data &a,const data &b) { if (a.a < b.a) //表示以南岸为关键字升序排 return 1; return 0; } int main() { //freopen("F:\rush.txt","r",stdin); scanf("%d",&n); for (int i =1;i <= n;i++) //先把线以南岸为关键字排序 scanf("%d%d",&city[i].a,&city[i].b); sort(city+1,city+1+n,cmp); for (int i = 1;i <= n;i++) m[i] = 1; for (int i = 2;i <= n;i++) for (int j = 1;j <= i-1;j++) //city[1..n].b就是北岸的各个位置 if (city[i].b>city[j].b && m[i] < m[j]+1) //求其最长不下降子序列 m[i] = m[j] + 1; int tm = m[1]; for (int i = 2;i <= n;i++) //求出f[1..n]中的最大值 并输出 if (m[i] > tm) tm = m[i]; printf("%d",tm); return 0; }