专栏文章
题解:P1027 [NOIP 2001 提高组] Car 的旅行路线
P1027题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mip218no
- 此快照首次捕获于
- 2025/12/03 04:52 3 个月前
- 此快照最后确认于
- 2025/12/03 04:52 3 个月前
这道题硬控我 小时。。。
题目难点:
主要是输入只告诉了我们三个点的坐标,所以需要求第四个点的坐标,要是每种情况都讨论一边的话代码比较长(但也能做),所以推荐写循环。剩下的就是最短路了,这里用 Floyd 就行了。
求第四点的方法:
初中数学中我们学到了两点间距离公式,中点公式和勾股定理,运用这三点,就能求出第四点的坐标了。
代码实现:
CPP代码实现:
void work(int xx) {
int ap, bp, cp; //cp代表直角三角形中斜边所对应的点,ap和bp代表另外两点
for(int i = 0; i <= 2; i++) {
for(int j = 0; j <= 2; j++) {
for(int l = 0; l <= 2; l++) {
if(i == j || j == l || i == l) continue;
double ka = dis2(a[xx].x[i], a[xx].y[i], a[xx].x[j], a[xx].y[j]);
double kb = dis2(a[xx].x[j], a[xx].y[j], a[xx].x[l], a[xx].y[l]);
double kc = dis2(a[xx].x[i], a[xx].y[i], a[xx].x[l], a[xx].y[l]);
if(ka + kb == kc) ap = l, bp = i, cp = j; //勾股定理判断是否构成直角三角形
else continue;
}
}
}
double midx = (a[xx].x[ap] + a[xx].x[bp]) / 2.0, midy = (a[xx].y[ap] + a[xx].y[bp]) / 2.0;
midx *= 2, midy *= 2;
newx = midx - a[xx].x[cp], newy = midy - a[xx].y[cp];
return;
}
最重要的一点,这里求两点间距离的 函数千万不要开根号,不然会有精度损失,导致没有答案。
函数实现:
CPP函数实现:
double dis2(double a1, double b1, double a2, double b2) {
return (a1 - a2) * (a1 - a2) * 1.0 + (b1 - b2) * (b1 - b2) * 1.0;
}
还有一个技巧:
除了 数组存每一个城市的机场坐标以及里程费以外,再开一个数组 ,保存每个机场的坐标以及从属的城市编号,这使后续操作方便许多。
就是这样:
CPP就是这样:
struct Node {
double x[5], y[5], t;
} a[N];
struct Nod {
int x, y, id;
} b[N];
这样,在最后求 到 城市的最少消耗时,就能够这样实现了(个人认为这样方便点):
CPPvoid print() {
double res = 1000000000.0;
for(int i = 1; i <= idx; i++) //idx表示机场个数
for(int j = 1; j <= idx; j++)
if(b[i].id == A && b[j].id == B)
if(res > f[i][j]) res = f[i][j];
printf("%.1lf\n", res);
}
最后,别忘了初始化做 Floyd 用的 数组。
完整代码实现:
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e2 + 5;
struct Node { double x[5], y[5], t; } a[N];
struct Nod { int x, y, id; } b[N];
int T, n, A, B, idx;
double t, newx, newy, f[N][N];
double dis2(double a1, double b1, double a2, double b2) { return (a1 - a2) * (a1 - a2) * 1.0 + (b1 - b2) * (b1 - b2) * 1.0; }
double dis(double a1, double b1, double a2, double b2) { return (double)sqrt((a1 - a2) * (a1 - a2) * 1.0 + (b1 - b2) * (b1 - b2) * 1.0); }
void work(int xx) {
int ap, bp, cp;
for(int i = 0; i <= 2; i++) {
for(int j = 0; j <= 2; j++) {
for(int l = 0; l <= 2; l++) {
if(i == j || j == l || i == l) continue;
double ka = dis2(a[xx].x[i], a[xx].y[i], a[xx].x[j], a[xx].y[j]);
double kb = dis2(a[xx].x[j], a[xx].y[j], a[xx].x[l], a[xx].y[l]);
double kc = dis2(a[xx].x[i], a[xx].y[i], a[xx].x[l], a[xx].y[l]);
if(ka + kb == kc) ap = l, bp = i, cp = j;
else continue;
}
}
}
double midx = (a[xx].x[ap] + a[xx].x[bp]) / 2.0, midy = (a[xx].y[ap] + a[xx].y[bp]) / 2.0;
midx *= 2, midy *= 2;
newx = midx - a[xx].x[cp], newy = midy - a[xx].y[cp];
return;
}
void init() {
for(int i = 1; i <= idx; i++) {
for(int j = 1; j <= idx; j++) {
if(b[i].id == b[j].id) f[i][j] = f[j][i] = dis(b[i].x, b[i].y, b[j].x, b[j].y) * a[b[i].id].t;
else f[i][j] = f[j][i] = dis(b[i].x, b[i].y, b[j].x, b[j].y) * t;
}
}
return;
}
void Floyd() {
for(int k = 1; k <= idx; k++)
for(int i = 1; i <= idx; i++)
for(int j = 1; j <= idx; j++)
if(f[i][j] > f[i][k] + f[k][j]) f[i][j] = f[i][k] + f[k][j];
return;
}
void print() {
double res = 1000000000.0;
for(int i = 1; i <= idx; i++)
for(int j = 1; j <= idx; j++)
if(b[i].id == A && b[j].id == B)
if(res > f[i][j]) res = f[i][j];
printf("%.1lf\n", res);
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
cin >> T;
while(T--) {
cin >> n >> t >> A >> B;
idx = 0;
for(int i = 1; i <= n; i++) {
cin >> a[i].x[0] >> a[i].y[0] >> a[i].x[1] >> a[i].y[1] >> a[i].x[2] >> a[i].y[2] >> a[i].t;
newx = newy = 0;
work(i);
a[i].x[3] = newx, a[i].y[3] = newy;
for(int j = 0; j <= 3; j++) b[++idx].id = i, b[idx].x = a[i].x[j], b[idx].y = a[i].y[j];
}
init(), Floyd(), print();
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...