Codevs5288 航线设计(动态规划加强版) 解题报告
??
有一個國家被一條河劃分為南北兩部分,在南岸和北岸總共有N對城鎮,每一城鎮在對岸都有唯一的友好城鎮。任何兩個城鎮都沒有相同的友好城鎮。每一對友好城鎮都希望有一條航線來往。于是他們向政府提出了申請。由于河終年有霧。政府決定不允許有任兩條航線交叉(如果兩條航線交叉,將有很大機會撞船)。
你的任務是寫一個程序來幫政府官員決定他們應撥款興建哪些航線以使得沒有出現交叉的航線最多。?
?
? ??
?【輸入格式】 ?
??
第一行一個整數N,表示分布在河兩岸的城鎮對數。接下來的N行每行有兩個由空格分隔的正數C,D(C、D<=10^9〉,描述每一對友好城鎮沿著河岸與西邊境線的距離,C表示北岸城鎮的距離而D表示南岸城鎮的距離。在河的同一邊,任何兩個城鎮的位置都是不同的。
?
? ??
?【輸出格式】 ?
? ?
在安全條件下能夠開通的最大航線數目。
?
? ??
?【輸入樣例】 ??
? ?
7
22 4
2 6
10 3
15 12
9 8
17 17
4 2
?
? ??
?【輸出樣例】 ?
? ?
4
?
? ??
?【數據范圍】 ?
? ?
1<=N<=500000
解題思路:根據題意,如果直接計算友好城鎮在安全條件下能開通的最大航線數目,不好知道哪些航線是交叉的,所以可以先將航線按北岸城鎮到邊境線的距離由小到大排序,則只有排序后每條航線對應的南岸城鎮到邊境線的距離也是由小到大遞增,才能保證航線沒有交叉(即滿足安全條件)。
所以該問題在排序后就變為了求最大單增子序列的問題,最簡單的想法就是動態規劃,設狀態函數f(i)表示前i對友好城鎮,以第i對友好城鎮為結尾時,在安全條件下能夠開通的最大航線數目,則狀態轉移方程為f(i)=max{f(j) | 1<=j<i && a[j].d<a[i].d && a[j].c<a[i].c},邊界條件即為f(0)=0,即沒有選擇友好城鎮時,能夠開通的最大航線數目為0。但這樣做的話,由于在狀態轉移時要查找滿足條件的最大的f(j),所需的時間復雜度為O(N^2),很明顯對于N最大達到500000的數據是過不了的,所以就要考慮優化。
因為在查找滿足條件的最大的f(j)時費了很多時間,如果能直接找到滿足條件的最大的f(j)就好了,于是想到可以利用數組,設數組g[i]表示長度為i的上升子序列的最后一個元素的最小值,因為g[i]在計算過程中始終是單調遞增(也有可能相鄰的兩個值相等)的(對于這一點,可以自己舉例來理解) ,所以如果知道f(i)所對應的第i對友好城鎮中南岸城鎮到邊境線的距離,就可以利用二分查找(lower_bound)找到第一個距離大于等于它第一個的上升子序列的長度,所求得的值即為f(i)的值(實際是將所求得的值先減1,再加1)。在計算f(i)的同時,要注意更新g[i]的值,如果查找時,第i對友好城鎮中南岸城鎮到邊境線的距離是最大的或者如果此時g[f(i)]的值比a[i].d大,那么g[f(i)]=a[i].d,同時因為要使用二分查找,就要記錄g數組的長度,如果查找時,第i對友好城鎮中南岸城鎮到邊境線的距離是最大的,g數組的長度就應該加1。需要注意的是,在編寫程序時,發現f(i)可以省略,在每次更新g數組后,g數組的長度就是答案。這種做法的時間復雜度為O(N*log2N)。
總結
以上是生活随笔為你收集整理的Codevs5288 航线设计(动态规划加强版) 解题报告的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript 调用本地exe文件
- 下一篇: 喷泉模型是什么?