TopCoder SRM417 Div1Hard

問題

平面上にいくつかの点があり、いくつかの点の間は道で結ばれている。道同士は端点以外で交差しない(しても接続しない)。2点間の最短距離は、道の上のみを通り、接続点のみで道を変えたときの最短距離である。道の上から2点選ぶとき、最短距離の最大値を求めよ。

解法

まず点の間でWarshal-Floyd。
その後、「2点間の最短距離」、「3点A,B,CでA--B--C--Aの最短距離の半分」、「4点A,B,C,Dでmin(A--B--C--D--A,A--B--D--C--A)/2」とすればよい。適当

コード

#include <vector>
#include <string>
#include <cmath>
#include <algorithm>

using namespace std;

class WalkingDistance
{
public:
	double getLongestShortest(vector<int> X, vector<int> Y, vector<string> S)
	{
		double ld[50][50], dist[50][50];
		for(int i=0;i<S.size();i++){
			for(int j=0;j<S.size();j++){
				if(i==j) dist[i][j] = 0;
				else{
					if(S[i][j]=='Y') dist[i][j] = sqrt(0.0 + (X[i]-X[j])*(X[i]-X[j]) + (Y[i]-Y[j])*(Y[i]-Y[j]));
					else dist[i][j] = 10000000;
				}
				ld[i][j] = dist[i][j];
			}
		}
		for(int i=0;i<S.size();i++){
			for(int j=0;j<S.size();j++){
				for(int k=0;k<S.size();k++){
					dist[j][k] = min(dist[j][k], dist[j][i] + dist[i][k]);
				}
			}
		}
		
		double ret = 0;
		for(int i=0;i<S.size();i++){
			for(int j=0;j<S.size();j++){
				ret = max(ret, dist[i][j]);
			}
		}
		for(int i=0;i<S.size();i++){
			for(int j=0;j<S.size();j++) if(ld[j][i]>0&&ld[j][i]<5000){
				for(int k=0;k<S.size();k++) if(i!=k&&j!=k){
					for(int l=0;l<S.size();l++) if(ld[k][l]>0&&ld[k][l]<5000&&j!=l&&k!=l){
						ret = max(ret, min(dist[i][j]+dist[j][k]+dist[k][l]+dist[l][i],dist[i][j]+dist[j][l]+dist[l][k]+dist[k][i])/2);
					}
				}
			}
		}
		
		return ret;
	}
};