题意:
平面上有一些圆 要求用最少的圆将1、2、3点连通 这三点上的圆必须使用
思路:
如果两圆可以连通 则用边把它们圆心相连 然后问题转化为图论模型 那么我们只需要从1、2、3求出到其他点的最短路 再枚举中间点分别到这三个点距离和即可
为什么这样找中间点是对的?? 因为虽然可能存在x->1和x->2的最短路经过y 但是如果y真的存在 那么最小值一定是y提供的 就算我们用x计算出错误的答案 它也不会是最后的答案
代码:
#include<stdio.h> #define N 205 #define inf 100000 int t, n, ans; int x[N], y[N], r[N], maz[N][N], dis[5][N], vis[N]; int min(int ff, int gg) { if (ff < gg) return ff; return gg; } void dij(int s) { int i, j, p, f; for (i = 1; i <= n; i++) { dis[s][i] = inf; vis[i] = 0; } dis[s][s] = 0; for (i = 1; i <= n; i++) { f = inf; for (j = 1; j <= n; j++) { if (!vis[j] && dis[s][j] < f) { f = dis[s][j]; p = j; } } vis[p] = 1; for (j = 1; j <= n; j++) { if (!vis[j] && maz[p][j] != inf && dis[s][j] > dis[s][p] + maz[p][j]) dis[s][j] = dis[s][p] + maz[p][j]; } } } int main() { int i, j; scanf("%d", &t); while (t--) { scanf("%d", &n); for (i = 1; i <= n; i++) scanf("%d%d%d", &x[i], &y[i], &r[i]); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { if ((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]) <= (r[i] + r[j]) * (r[i] + r[j])) maz[i][j] = 1; else maz[i][j] = inf; } maz[i][i] = 0; } for (i = 1; i <= 3; i++) dij(i); ans = inf; for (i = 1; i <= n; i++) { ans = min(ans, dis[1][i] + dis[2][i] + dis[3][i]); } if (ans == inf) printf("-1\n"); else printf("%d\n", n - ans - 1); } return 0; }
原文地址:http://blog.csdn.net/houserabbit/article/details/39801829