Niu's Travel(Informatics Olympics One Book Pass-T1343)

タイトル説明
ファーマージョンの農場には多くの牧草地があり、いくつかの小道は特定の牧草地を接続しており、接続されているすべての牧草地は牧草地と呼ばれます。

しかし、今のところ、少なくとも2つの牧歌的なエリアが切断されていることがわかります。ここで、ジョンはファームへのパスを追加したいと考えています(1つだけあることに注意してください)。

この経路にはそのような制限があります。牧草地の直径は、牧草地の中で最も遠い2つの牧草地の間の最短距離です。

次の2つの牧草地について考えてみます。図1は、5つの牧草地がある牧草地です。牧草地は「*」で表され、パスは直線で表され、各牧草地には独自の座標があります。

図1に示す牧草地の直径は約12.07106で、最も遠い2つの牧草地はAとEであり、それらの間の最短経路はABEです。
ここに画像の説明を挿入

これらの牧場は両方ともジョンの農場にあり、

ジョンは、2つの牧草地のそれぞれで牧草地エリアを選択し、接続後に新しい大きな牧草地の直径が最小になるように、パスでそれらを接続します。

2つのパスが途中で交差する場合、それらが接続されているとは見なされないことに注意してください。2つのパスが同じ牧歌的なエリアで交差する場合にのみ、それらが接続されていると見なすことができます。

次に、2つの異なる牧草地を接続するパスを見つけるようにプログラムするように依頼します。これにより、このパスを接続した後、この大きな新しい牧草地の直径が最小になります。

入力形式
1行目:牧歌的な領域の数を表す整数N;
2行目からN + 1:各行に2つの整数X、Y、N個の牧歌的な領域の座標を表します。各牧歌的なエリアの座標は異なります。
行N + 2から行2 * N + 1:各行には、対称隣接行列を示すN個の数値(0または1)が含まれます。

たとえば、タイトルの説明にある2つの牧草地のマトリックスの説明は次のとおりです。

ABCDEFGH
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

入力データには、少なくとも2つの切断された牧歌的な領域が含まれます。

出力形式は
、希望する答えを表す実数を含む1行のみです。数値は小数点以下6桁です。

入力例
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

サンプル出力
22.071068

データ範囲
1≤N≤150
0≤X、Y≤10 5


問題解決
フロイド:

解题步骤

  1. もう一度やり直しFloyd、各ポイントが到達できる最も遠い距離MAX_len[i]を見つけ、牧草地の最大直径を見つけますR
  2. 接続されていないすべてのポイントをトラバースします。接続されていない場合i、jは、最大距離の後に接続を確立できますMAX_len[i] + get_distance(i, j) + MAX_len(j)
  3. 接続距離が原因で、元の牧草地の最大直径よりも小さい場合がRあり连线后的距离最小值ますmax
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;

typedef pair<int, int> PII;

const int N = 160;
const double INF = 0x3f3f3f3f;

int n;
PII q[N];
double d[N][N], MAX_len[N];
char g[N][N];

double get_distance(int a, int b)
{
    
    
    int dx = q[a].first - q[b].first;
    int dy = q[a].second - q[b].second;
    return sqrt(dx * dx + dy * dy);
}

int main()
{
    
    
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> q[i].first >> q[i].second;
    for (int i = 1; i <= n; i ++) cin >> g[i] + 1;
    
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= n; j ++)
            if(i != j)
            {
    
    
                if(g[i][j] == '1') d[i][j] = get_distance(i, j);
                else d[i][j] = INF;
            }
            
    for (int k = 1; k <= n; k ++)
        for (int i = 1; i <= n; i ++)
            for (int j = 1; j <= n; j ++)
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
          
    double R = 0;            
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= n; j ++)
            if(d[i][j] != INF)
            {
    
    
                MAX_len[i] = max(MAX_len[i], d[i][j]);
                R = max(R, MAX_len[i]);    
            }
                
    double ans = INF;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= n; j ++)
            if(d[i][j] == INF)
                ans = min(ans, get_distance(i, j) + MAX_len[i] + MAX_len[j]);
                
    printf("%.6f", max(R, ans));            
    return 0;
}

おすすめ

転載: blog.csdn.net/weixin_46239370/article/details/113837311