【最短路】【图论】【Floyed】牛的旅行(ssl 1119/luogu 1522)
生活随笔
收集整理的這篇文章主要介紹了
【最短路】【图论】【Floyed】牛的旅行(ssl 1119/luogu 1522)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
牛的旅行
ssl 1119
luogu 1522
題目大意
有兩堆點,每一堆點之中的任何兩個點都一定有相連的路線,連接兩堆點中的各一個點,使最遠的兩個點的距離最短
原題
農民John的農場里有很多牧區。有的路徑連接一些特定的牧區。一片所有連通的牧區稱為一個牧場。但是就目前而言,你能看到至少有兩個牧區不連通。這樣,農民John就有多個牧區了。
John想在農場里添加一條路徑(注意,恰好一條)。對這條路徑有以下限制:
一個牧場的直徑就是牧場中最遠的兩個牧區的距離(本題中所提到的所有距離指的都是最短的距離)。考慮如下的有5個牧區的牧場,牧區用星號表示,路徑用直線表示。每一個牧區都有自己的坐標:
這個牧場的直徑大約是12.07106,最遠的兩個牧區是A和E,它們之間的最短路徑是A-B-E。
這里是另一個牧場:
這兩個牧場都在John的農場上。John將會在兩個牧場中各選一個牧區,然后用一條路徑連起來,使得連通后這個新的更大的牧場有最小的直徑。
注意,如果兩條路徑中途相交,我們不認為它們是連通的。只有兩條路徑在同一個牧區相交,我們才認為它們是連通的。
輸入文件包括牧區、它們各自的坐標,還有一個如下的對稱鄰接矩陣:
A B C D E F G H
A 0 1 0 0 0 0 0 0
B 1 0 1 1 1 0 0 0
C 0 1 0 0 1 0 0 0
D 0 1 0 0 1 0 0 0
E 0 1 1 1 0 0 0 0
F 0 0 0 0 0 0 1 0
G 0 0 0 0 0 1 0 1
H 0 0 0 0 0 0 1 0
輸入文件至少包括兩個不連通的牧區。
請編程找出一條連接兩個不同牧場的路徑,使得連上這條路徑后,這個更大的新牧場有最小的直徑。
Input
第1行: 一個整數N (1 <= N <= 150), 表示牧區數
第2到N+1行: 每行兩個整數X,Y (0 <= X ,Y<= 100000), 表示N個牧區的坐標。注意每個 牧區的坐標都是不一樣的。
第N+2行到第2*N+1行: 每行包括N個數字(0或1) 表示如上文描述的對稱鄰接矩陣。
Output
只有一行,包括一個實數,表示所求答案。數字保留六位小數。
Sample Input
8
10 10
15 10
20 10
15 15
20 15
30 15
25 10
30 10
01000000
10111000
01001000
01001000
01110000
00000010
00000101
00000010
Sample Output
22.071068
解題方法:
先求出兩個區塊的最短路,再求出每個區塊中每個點與相距此點最大的點的距離,枚舉兩邊的所有點,將任意兩個點(不同區域)連接后的的結果就是兩個點的距離加上兩個點在本區域的相差最大的距離(若不懂,看代碼)
注意:
當出現下圖時(推薦按住左鍵再移動來放大圖片),要連接3和4,但最大長度不是1-3-4或2-3-4,而是1-2,所以要注意
#include<cstdio> #include<cmath> #include<iostream> #include<cstring> #include<algorithm> #include<string> using namespace std; int n; double f[152][152],b[152],jl[152][152],ans,g,sum; char t; struct rec {int x,y; }a[152]; int main() {scanf("%d",&n);for (int i=1;i<=n;i++)scanf("%d %d",&a[i].x,&a[i].y);memset(f,0x7f,sizeof(f));//初值memset(jl,0x7f,sizeof(jl));g=f[0][0];//記錄最大值for (int i=1;i<=n;i++){getchar();//換行for (int j=1;j<=n;j++){t=getchar();//輸入jl[i][j]=sqrt(double((a[i].x-a[j].x)*(a[i].x-a[j].x))+double((a[i].y-a[j].y)*(a[i].y-a[j].y)));//用勾股定理求距離if (t=='1') f[i][j]=jl[i][j];//f用來求最短路}}for (int k=1;k<=n;k++)for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)if ((i!=j)&&(j!=k)&&(k!=i)&&(f[i][k]+f[k][j]<f[i][j]))f[i][j]=min(f[i][k]+f[k][j],f[i][j]);//求最短路for (int i=1;i<=n;i++){for (int j=1;j<=n;j++)if (f[i][j]!=g)b[i]=max(f[i][j],b[i]);//求距離最長的sum=max(sum,b[i]);//記錄}ans=g;for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)if ((f[i][j]==g)&&(i!=j))//要不同區ans=min(ans,b[i]+b[j]+jl[i][j]);//連接printf("%.6lf",max(ans,sum));//輸出最大的return 0; }溫馨提示:
在luogu中要用scanf("%s")來一行一行地輸入字符數組
總結
以上是生活随笔為你收集整理的【最短路】【图论】【Floyed】牛的旅行(ssl 1119/luogu 1522)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 万能的打印文档设置Word文档打印设置
- 下一篇: 【图论】【最短路】【Dijkstra】最