题意
有两条平行直线(L_1:Ax + By + C_1 = 0),(L_2:Ax + By + C_2 = 0),有n个圆(C_i:(x - x_i)^2 + (y - y_i)^2 = r_i^2)。人在直线上、圆上、圆内行走不消耗体力。在其它位置上由S点走到T点消耗的体力为S和T的欧几里得距离。问从(L_1)走到(L_2)需要的最少体力。((n le 1000))
题解
代码
const int N = 1005;
int n;
bool use[N];
double A, B, C1, C2;
double cost[N][N], d[N];
void DJS(int st) {
rep(i, 0, N) use[i] = 0, d[i] = INF32 * 1.0;
d[st] = 0;
while(true) {
int u = -1;
Rep(i, 1, n + 2) if (!use[i] && (u == -1 || d[i] < d[u])) u = i;
if (u == -1) break;
use[u] = 1;
Rep(i, 1, n + 2) d[i] = min(d[i], d[u] + cost[u][i]);
}
printf("%.6f
", d[n + 2]);
}
struct Point {
double x, y, r;
} p[N];
double compute(double x1, double y1, double x2, double y2) {
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
int main()
{
cin >> n >> A >> B >> C1 >> C2;
Rep(i, 1, n) cin >> p[i].x >> p[i].y >> p[i].r;
Rep(i, 1, n) {
Rep(j, i + 1, n) {
double tp = compute(p[i].x, p[i].y, p[j].x, p[j].y);
cost[i][j] = cost[j][i] = max(0.0, tp - p[i].r - p[j].r);
}
}
Rep(i, 1, n) {
double tp = fabs(A * p[i].x + B * p[i].y + C1) / sqrt(A * A + B * B) - p[i].r;
double sp = fabs(A * p[i].x + B * p[i].y + C2) / sqrt(A * A + B * B) - p[i].r;
cost[n + 1][i] = cost[i][n + 1] = max(0.0, tp);
cost[n + 2][i] = cost[i][n + 2] = max(0.0, sp);
}
cost[n + 1][n + 2] = cost[n + 2][n + 1] = fabs(C1 - C2) / sqrt(A * A + B * B);
DJS(n + 1);
return 0;
}