1 条题解
-
1
这道题思考不难,但比较考察代码能力。打了一个小时,调了三个小时👀️。
第一步:需要计算出另一个城市的坐标,用两点坐标公式加以变形即可。
第二步:导入各种的边,注意是无向图,要考虑双向。
第三步:spfa或dijkstra计算最短路即可(好像floyd也可以)
剩下的看代码吧。
#include<bits/stdc++.h> using namespace std; #define p pair<int, int> //这里我用pair把横坐标和纵坐标绑在一起 #define s(n) scanf("%d",&n); int s,t,a,b,n,cnt = 1; struct city{ p cs[5]; int tt; }c[110]; struct edge{ p begin,end; double data; int next; }edges[200010]; map<p, int> head; // 使pair与int相对应 这里用map来解决 map用法很像list inline void init(p bb, p ee, double dd){ edges[cnt].begin = bb; edges[cnt].end = ee; edges[cnt].data = dd; edges[cnt].next = head[bb]; head[bb] = cnt++; } inline void cinit(struct city *cc){ //读入城市 s(cc->cs[1].first);s(cc->cs[1].second); s(cc->cs[2].first);s(cc->cs[2].second); s(cc->cs[3].first);s(cc->cs[3].second); s(cc->tt); //计算剩下一个城市的坐标 double tri1 = pow(cc->cs[1].first - cc->cs[2].first, 2) + pow(cc->cs[1].second - cc->cs[2].second, 2); double tri2 = pow(cc->cs[2].first - cc->cs[3].first, 2) + pow(cc->cs[2].second - cc->cs[3].second, 2); double tri3 = pow(cc->cs[1].first - cc->cs[3].first, 2) + pow(cc->cs[1].second - cc->cs[3].second, 2); if(tri1 > tri2 && tri1 > tri3){ cc->cs[4].first = cc->cs[1].first + cc->cs[2].first - cc->cs[3].first; cc->cs[4].second = cc->cs[1].second + cc->cs[2].second - cc->cs[3].second; } else{ if(tri2 > tri1 && tri2 > tri3){ cc->cs[4].first = cc->cs[2].first + cc->cs[3].first - cc->cs[1].first; cc->cs[4].second = cc->cs[2].second + cc->cs[3].second - cc->cs[1].second; } else{ cc->cs[4].first = cc->cs[1].first + cc->cs[3].first - cc->cs[2].first; cc->cs[4].second = cc->cs[1].second + cc->cs[3].second - cc->cs[2].second; } } // 导入铁路边 (构图) for(int i=1;i<=4;i++) //要先将head初始化一下 head[cc->cs[i]] = -1; for(int i=1;i<=4;i++){ //每个城市都要加3条边,所以双向边就包含在内了。 for(int j=1;j<=4;j++){ double dt = cc->tt * sqrt( pow(cc->cs[i].first - cc->cs[j].first, 2) + pow(cc->cs[i].second - cc->cs[j].second, 2) ); if(i != j){ init(cc->cs[i], cc->cs[j], dt); } } } } queue<p> q; map<p, double> dis,flag; double ans = INT_MAX; inline void spfa(){ //正经的spfa,我用的堆优化 for(int i=1;i<=4;i++){ for(int z=1;z<=s;z++){ //初始化dis和flag for(int j=1;j<=4;j++){ dis[c[z].cs[j]] = 1061109567; flag[c[z].cs[j]] = 0; } } dis[c[a].cs[i]] = 0; flag[c[a].cs[i]] = 1; q.push(c[a].cs[i]); while(!q.empty()){ p f = q.front(); for(int j = head[f]; ~j; j = edges[j].next){ p ec = edges[j].end; if(dis[ec] > dis[f] + edges[j].data){ dis[ec] = dis[f] + edges[j].data; if(!flag[ec]){ q.push(ec); flag[ec] = 1; } } } q.pop(); flag[f] = 0; } for(int j=1;j<=4;j++) ans = min(ans, dis[c[b].cs[j]]); //计算最小值 } } int main(){ s(n); for(int i=0;i<n;i++){ s(s);s(t);s(a);s(b); for(int i=1;i<=s;i++){ cinit(&c[i]); } for(int i=1;i<=s;i++){ //导入飞行航线,构图 for(int z=1;z<=4;z++){ for(int j=1;j<=s;j++){ if(i >= j) continue; //这个很重要,因为我后边加了双向边,所以必须每个城市只考虑一次,就是1->2,1->3,2->3,然后结束 for(int v=1;v<=4;v++){ double dt = sqrt( pow(c[i].cs[z].first - c[j].cs[v].first, 2) + pow(c[i].cs[z].second - c[j].cs[v].second, 2) ); init(c[i].cs[z], c[j].cs[v], dt*t); init(c[j].cs[v], c[i].cs[z], dt*t); } } } } spfa(); printf("%.1f\n",ans); } return 0; }
- 1
信息
- ID
- 1746
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 23
- 已通过
- 13
- 上传者