「GOI-R1」 不卜庐 官方题解
不卜庐 官方题解
题意描述:
在一个平面直角坐标系中,起点为
思路:
容易看出对答案有贡献的点就只有所有道具。由于我们不知道答案到底用了几次道具,因而可以列举我们到达某个点使用
起点的道具必须用,因此可以直接跳过。我们将起点道具以及另外
其中
代码如下:
#include <iostream>
#include <cmath>
using namespace std;
const int N = 510;
const int K = 110;
int n, m, s, t, x, y;
double ans, dp[N][K];
struct node {
int a, b;
}p[N];
int len(int a, int b) {
return abs(p[a].a - p[b].a) + abs(p[a].b - p[b].b);
}
int main() {
for (int i = 0; i <= 509; i ++)
for (int j = 0; j <= 109; j ++)
dp[i][j] = 1e6;//初始化
scanf("%d%d%d%d%d%d", &n, &m, &s, &t, &x, &y);
m --;//起点道具必须使用,否则无法移动
p[0].a = x, p[0].b = y, p[1].a = s, p[1].b = t;//重新标点并把终点存储在0号下标处
for (int i = 2; i <= n + 1; i ++) scanf("%d%d", &p[i].a, &p[i].b);
n ++;
dp[1][0] = 0, ans = len(0, 1);//也可以不使用其它道具直接到达终点
for (int i = 2; i <= n; i ++) dp[i][0] = len(1, i);//因为速度为1,不使用道具时间花费即为距离
for (int r = 1; r <= m; r ++) {//列举使用道具次数
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= n; j ++) {
if (i == j) continue;
dp[i][r] = min(dp[i][r], dp[j][r - 1] + (double)len(i, j) / r);//转移
}
ans = min(ans, dp[i][r] + (double)len(0, i) / (r + 1));//更新答案
}
}
printf("%.12lf", ans);
return 0;
}