TYVJ 1069 cowtour 解题报告
USACO原题,做过几次了,所以一次AC,就是暴搜,因为数据小。
先把每个牧区的直径求出来,然后再把在一个牧区中距离任意节点的最远距离算出来,然后暴搜,若i,j之间加一条路,那么新牧区的半径要么就是i所在的牧区的的直径,要么是j所在的牧区的直径,要么就是i所在的牧区中距i最远的距离加上j所在的牧区中距j最远的距离加上i,j之间的距离。
看代码最有效:
#include <math.h> #include <stdio.h> #include <stdlib.h> #define INF 100000000 struct dot{ int x, y; }dot[150]; int n; double dis[150][150]; double dir[150]; int group[150]; double maxdis[150]; char can[150][150]; double getdis(int a, int b) { double t; t = sqrt((double)(dot[a].x - dot[b].x) * (dot[a].x - dot[b].x) + (dot[a].y - dot[b].y) * (dot[a].y - dot[b].y)); return t; } void makegroup(int a, int b) { int i; group[a] = b; for(i = 0; i < n; i++){ if(can[a][i] && group[i] != b){ makegroup(i, b); } } } void init(void) { int i, j; scanf("%d\n", &n); for(i = 0; i < n; i++){ scanf("%d%d\n", &dot[i].x, &dot[i].y); } for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ scanf("%c", &can[i][j]); can[i][j] -= '0'; //确实不知道这个i == j, dis = 0可以影响程序的运行 //刚刚仔细查了一下, 原来是在获取dis[i][i]的时候得到了错误的值(非0) //然后再计算半径的时候就使用了那个错误的较大的值, 导致程序错了. if(i == j){ dis[i][j] = 0; }else if(can[i][j] == 0){ dis[i][j] = INF; }else{ dis[i][j] = getdis(i, j); } } scanf("\n"); } } int main(int argc, char **argv) { int i, j, k; double ans = INF, t; init(); for(i = 0, j = 1; i < n; i++){ if(!group[i]){ makegroup(i, j); j++; } } for(k = 0; k < n; k++){ for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ if(group[i] == group[j] && group[i] == group[k]){ if(dis[i][j] > dis[i][k] + dis[k][j]){ dis[i][j] = dis[i][k] + dis[k][j]; } } } } } for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ if(group[i] == group[j] && dir[group[i]] < dis[i][j]){ dir[group[i]] = dis[i][j]; } if(group[i] == group[j] && maxdis[i] < dis[i][j]){ maxdis[i] = dis[i][j]; } } } for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ if(group[i] == group[j]){ continue; } t = maxdis[i] + maxdis[j] + getdis(i, j); if(t < dir[group[i]]){ t = dir[group[i]]; } if(t < dir[group[j]]){ t = dir[group[j]]; } if(ans > t){ ans = t; } } } printf("%.6lf", ans); return 0; }