【dp】船
船
(ships.pas/c/cpp)
???????????????????? 來源:《奧賽經典》(提高篇)
【問題描述】
PALMIA國家被一條河流分成南北兩岸,南北兩岸上各有N個村莊。北岸的每一個村莊有一個唯一的朋友在南岸,且他們的朋友村莊彼此不同。
每一對朋友村莊想要一條船來連接他們,他們向政府提出申請以獲得批準。由于河面上常常有霧,政府決定禁止船只航線相交(如果相交,則很可能導致碰船)。
你的任務是編寫一個程序,幫助政府官員決定批準哪些船只航線,使得不相交的航線數目最大。
【輸入文件】ships.in
??? 輸入文件由幾組數據組成。每組數據的第一行有2個整數X,Y,中間有一個空格隔開,X代表PALMIA河的長度(10<=X<=6000),Y代表河的寬度(10<=Y<=100)。第二行包含整數N,表示分別坐落在南北兩岸上的村莊的數目(1<=N<=5000)。在接下來的N行中,每一行有兩個非負整數C,D,由一個空格隔開,分別表示這一對朋友村莊沿河岸與PALMIA河最西邊界的距離(C代表北岸的村莊,D代表南岸的村莊),不存在同岸又同位置的村莊。最后一組數據的下面僅有一行,是兩個0,也被一空格隔開。
【輸出文件】ships.out
????? 對輸入文件的每一組數據,輸出文件應在連續的行中表示出最大可能滿足上述條件的航線的數目。
【輸入樣例】
30 4
7
22 4
2 6
10 3
15 12
9 8
17 17
4 2
0 0
【輸出樣例】
4
【問題分析】
這道題目相對來說思考難度較高,從字面意義上看不出問題的本質來,有點無法下手的感覺。這里我給大家推薦兩種思考這類問題的方法。
法一:尋找規律法(我前面總結提到的第3個方法)
尋找規律自然要推幾組數據,首先當然要從樣例入手;
?
仔細觀察上圖:紅色航線是合法的,那么他們滿足什么規律呢?
???????????????? C1??? C2?? C3?? C4
北岸紅線的端點: 4???? 9??? 15?? 17
南岸紅線的端點: 2???? 8??? 12?? 17
???????????????? D1??? D2?? D3?? D4
不難看出無論線的斜率如何,都有這樣的規律:
C1<C2<C3<C4 且? D1<D2<D3<D4
如果我們把輸入數據排升序,問題變抽象為:
在一個序列(D)里找到最長的序列滿足DI<DJ<Dk……且i<j<k
這樣的話便是典型的最長非降子序列問題了。。。。
法二:邊界條件法(我前面總結提到的第4個方法)
邊界法其實就是把數據往小了縮,顯然N=1是答案是1。N=2時呢?
考慮這樣一組數據:
N=2
C1??? D1
C2??? D2
當 C1<C2 時,如果D1>D2 那么一定會相交,反之則不會相交。
當C1? >C2時,如果D1<D2 那么一定會相交,反之則不會相交。
N=3
C1??? D1
C2??? D2
C3??? D3
……
其實不用在推導N=3了,有興趣的可以推導去。看N=2時就能得出:
對于任意兩條航線如果滿足Ci<Cj 且Di<Dj 則兩條航線不相交。這樣的話要想在一個序列里讓所有的航線都不相交那比然滿足,C1<C2<C3…Cans且D1<D2<D3…<Dans ,也就是將C排序后求出最長的滿足這個條件的序列的長度就是解。
這樣分析后顯然是一個最長非降子序列問題。
復雜度:排序可以用O(nlogn)的算法,求最長非降子序列時間復雜度是O(n2).
總復雜度為O(n2).
?
1 #include<iostream> 2 #include<algorithm> 3 #include<string> 4 #include<vector> 5 #include<set> 6 #include<queue> 7 #include<map> 8 #include<stack> 9 #include<iterator> 10 #include<cstdio> 11 #include<cstring> 12 #include<cstdlib> 13 #include<cmath> 14 using namespace std; 15 typedef long long ll; 16 typedef unsigned long long ull; 17 #define clr(c) memset(c, 0, sizeof(c)); 18 #define pi acos(-1.0) 19 const int INF = 0x3f3f3f3f; 20 const int mod = 1e9 + 7; 21 const double eps = 1e-8; 22 typedef struct point{ 23 int x, y; 24 bool operator < (const point& p) const{ 25 if (x == p.x) return y < p.y; 26 else return x < p.x; 27 } 28 bool operator >(const point& p) const{ 29 return p < *this; 30 } 31 }p; 32 int x, y; 33 int n; 34 p arr[1005]; 35 int dp[1005]; 36 37 int main(){ 38 while(~scanf("%d%d", &x, &y)){ 39 if(x==0 && y==0) break; 40 scanf("%d", &n); 41 for(int i = 0; i < n; i++){ 42 int a, b; 43 scanf("%d%d", &a, &b); 44 arr[i].x = a, arr[i].y = b; 45 } 46 sort(arr, arr+n); 47 for(int i = 0; i < n; i++) dp[i] = 1; 48 int ans = 0; 49 for(int i = 0; i < n; i++){ 50 for(int j = 0; j < i; j++){ 51 if(arr[i].y > arr[j].y && dp[j]+1 > dp[i]) dp[i] = dp[j]+1; 52 } 53 if(dp[i] > ans) ans = dp[i]; 54 } 55 printf("%d\n", ans); 56 } 57 58 return 0; 59 }
?
轉載于:https://www.cnblogs.com/miaowTracy/p/5932393.html
總結
- 上一篇: PetaPoco - 轻量级高性能的OR
- 下一篇: Html中各种空格的显示