日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Codevs5288 航线设计(动态规划加强版) 解题报告

發布時間:2024/1/1 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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)。


#include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int maxn=500005; int N; struct data {int c,d; }; data a[maxn]; bool cmp(data aa,data bb) {return aa.c<bb.c; } /* f(i)表示前i對城鎮,以第i對城鎮為結尾時,在安全條件下能夠開通的最大航線數目 f(i)=max{f(j) | 1<=j<i && a[j].d<a[i].d} 邊界:f(0)=0 */ int g[maxn]; //g[i]表示長度為i的上升子序列的最后一個元素的最小值 void solve() {int cnt=0; //記錄g數組的長度for(int i=1;i<=N;i++){int t=lower_bound(g+1,g+1+cnt,a[i].d)-g; //查找距離大于等于第i對友好城鎮中南岸城鎮到邊境線的距離的第一個上升子序列長度,即為當前的答案if(t>cnt || g[t]>a[i].d) g[t]=a[i].d; //更新g[i]if(t>cnt) cnt=t; //更新g數組長度}printf("%d\n",cnt); } int main() {//freopen("48.in","r",stdin);//freopen("48.out","w",stdout);scanf("%d",&N);for(int i=1;i<=N;i++)scanf("%d%d",&a[i].c,&a[i].d); //將友好城鎮按北岸城鎮到邊境線的距離由小到大排序sort(a+1,a+1+N,cmp);solve();return 0; }

總結

以上是生活随笔為你收集整理的Codevs5288 航线设计(动态规划加强版) 解题报告的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。