1. 程式人生 > >【DP】友好城市

【DP】友好城市

題目描述

Palmia國有一條橫貫東西的大河,河有筆直的南北兩岸,岸上各有位置各不相同的N個城市。北岸的每個城市有且僅有一個友好城市在南岸,而且不同城市的友好城市不相同。 每對友好城市都向政府申請在河上開闢一條航線連線兩個城市,但是由於河上經常起大霧,政府決定避免任意兩條航線交叉,以避免事故。請程式設計幫助政府做出一些批准和拒絕申請的決定,使得在保證任意兩條航線不相交的情況下,被批准的申請儘量多。

輸入

第1行,一個整數N(1<=N<=5000),表示城市數。 第2行到第n+1行,每行兩個整數,分別表示南岸和北岸的一對友好城市的座標。(0<=xi<=10000)

輸出

一行,輸出一個整數,表示政府所能批准的最多申請數。

輸入樣例
7
22 4
2 6
10 3
15 12
9 8
17 17
4 2
輸出樣例
4

思路:

原本以為很難,結果聽了一下別人講,才發現其實還算挺簡單的,首先把南岸從小到大快排(北岸一起動),然後求北岸的最長上升子序列的長度。 排序完後是這樣:

北岸 南岸
2 6
4 2
9 8
10 3
15 12
17 17
22 4

求北岸的最長上升子序列的長度。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std; struct wah { int a,b;//a是南岸座標,b是北岸座標 }; wah a[100002]; int n,f[100002];//f[i]是存以i結尾的最長上升子序列的長度 void qsort(int l,int r)//不要問我為什麼把快排敲上了 { if(l>=r)return; int k=a[(l+r)/2].a; int i=l,j=r; while(i<=j) { while(a[i].a<k)i++; while(a[j].a>k)j--; if(i<=j) { swap(a[i],a[
j]); i++;j--; } } qsort(l,j); qsort(i,r); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&a[i].a,&a[i].b); qsort(1,n); int maxx=1;//maxx是最長上升子序列的長度 for(int i=1;i<=n;i++) { f[i]=1; for(int j=i-1;j>=1;j--) { if(a[j].b<a[i].b && f[j]>=f[i])f[i]=f[j]+1;//如果a[j]的值小於a[i]的值和以j結尾的長度小於以i結尾的長度,就賦為以j結尾的子序列加上a[i].b。 maxx=max(f[i],maxx);//判斷最長子序列的長度 } } printf("%d",maxx); return 0; }