USACO 2.4 Cow Tours (Floyd最短路径 + DFS)

#include <stdio.h>
#include <math.h>
#define DEBUG 1
#define TESTCASES 9
#define MAX_PASTUERS 150
#define INF 1e10

int numOfPastures;
typedef struct Location{
	int x;
	int y;
}Location;
Location pastureArray[MAX_PASTUERS + 1];
double distance[MAX_PASTUERS + 1][MAX_PASTUERS + 1];
int field[MAX_PASTUERS + 1];
//diameter[pasture]表示以牧区pasture为端点的直径,也就是牧区pasture到同个牧场的其他牧区的最长距离
double diameter[MAX_PASTUERS + 1];
double fieldDiameter[MAX_PASTUERS + 1];

double getDistance(Location from, Location to){
	double deltaX = from.x - to.x;
	double deltaY = from.y - to.y;
	return sqrt(deltaX * deltaX + deltaY * deltaY);
}

void mark(int from, int fieldNum){
	if (field[from] != -1)
		return;
	field[from] = fieldNum;

	int to;
	for (to = 1; to <= numOfPastures; to++)
		if (distance[from][to] < INF)
			mark(to, fieldNum);
}

int main(){
#if DEBUG
	int testCase;
	for (testCase = 1; testCase <= TESTCASES; testCase++){
		char inputFileName[20] = "inputX.txt";
		inputFileName[5] = '1' +  (testCase - 1);
		freopen(inputFileName, "r", stdin);
		printf("\n#%d\n", testCase);
#endif

	scanf("%d", &numOfPastures);
	int pasture;
	for (pasture = 1; pasture <= numOfPastures; pasture++)
		scanf("%d%d", &pastureArray[pasture].x, &pastureArray[pasture].y);

	//建图
	char cha;
	scanf("%c", &cha);
	int from, to;
	for (from = 1; from <= numOfPastures; from++){
		for (to = 1; to <= numOfPastures; to++){
			scanf("%c", &cha);
			if (from == to)
				distance[from][to] = 0.0;
			else if (cha == '0')
				distance[from][to] = INF;
			else
				distance[from][to] = getDistance(pastureArray[from], pastureArray[to]);
		}
		scanf("%c", &cha);
	}

	//Floyd求任意两点之间最短路径
	int pass;
	for (pass = 1; pass <= numOfPastures; pass++)
		for (from = 1; from <= numOfPastures; from++)
			for (to = from + 1; to <= numOfPastures; to++)
				if (distance[from][pass] + distance[pass][to] < distance[from][to])
					distance[from][to] = distance[to][from] = distance[from][pass] + distance[pass][to];

	for (pasture = 1; pasture <= numOfPastures; pasture++)
		field[pasture] = -1;
	int numOfFields = 0;
	
	//用DFS标识牧区pasture是属于哪个牧场field
	for (pasture = 1; pasture <= numOfPastures; pasture++)
		if (field[pasture] == -1)
			mark(pasture, ++numOfFields);

	for (pasture = 1; pasture <= numOfPastures; pasture++)
		diameter[pasture] = 0;
	int fieldNum;
	for (fieldNum = 1; fieldNum <= numOfFields; fieldNum++)
		fieldDiameter[fieldNum] = 0;

	//求出diameter数组和牧场filed半径数组
	for (from = 1; from <= numOfPastures; from++){
		for (to = 1; to <= numOfPastures; to++)
			if (distance[from][to] < INF &&  distance[from][to] > diameter[from])
				diameter[from] = distance[from][to];
		if (diameter[from] > fieldDiameter[ field[from] ])
			fieldDiameter[ field[from] ] = diameter[from];
	}

	//连接牧场
	double minNewDiameter = INF;
	for (from = 1; from <= numOfPastures; from++)
		for (to = from + 1; to <= numOfPastures; to++){
			if (distance[from][to] != INF)
				continue;
			double newDiameter = diameter[from] + diameter[to] + getDistance(pastureArray[from], pastureArray[to]);
			//注意这样求出来的newDiameter有可能比连通后的新牧场半径小
			if (newDiameter < minNewDiameter)
				minNewDiameter = newDiameter;
		}
	
	//连通后的牧场半径不可能小于原牧场的半径
	for (fieldNum = 1; fieldNum <= numOfFields; fieldNum++)
		if (fieldDiameter[fieldNum] > minNewDiameter)
			minNewDiameter = fieldDiameter[fieldNum];

	printf("%.6lf\n", minNewDiameter);

#if DEBUG
	}
#endif
	return 0;
}


 
 
 

你可能感兴趣的:(最短路径,USACO,DFS,COW,2.4,Tours)