Car的旅行路线 codevs1041 最短路

56 篇文章 0 订阅
16 篇文章 0 订阅

Description


给T组数据n个矩形的任意三个点,i矩阵内部的同路费用为 Vi ,不同矩阵间的单位费用为 V <script type="math/tex" id="MathJax-Element-58">V</script>,求A矩阵到B矩阵的最小费用
这里的起点和终点可以是四点中的任意一点

Solution


嗯光是输入就想了好久呀
这里引入一个定理

已知平行四边形的三点(x1,y1)(x2,y2)(x3,y3),那么第四点为(x1+x3-x2,y1+y3-y2),情况分三种

由于这里是矩形,我们只用考虑直角对边就行了

最短路就没什么好说的了

Code


#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define fill(x, t) memset(x, t, sizeof(x)) 
#define EPS 0.001
#define db double
#define INF 0x3f3f3f3f
#define N 40001
#define E N * 21 + 1
struct edge{int x, y; db w; int next;}e[E];
struct pos{
    int x, y;
    pos operator +(pos b)const{
        pos a = *this;
        return (pos){a.x + b.x, a.y + b.y};
    }
    pos operator -(pos b)const{
        pos a = *this;
        return (pos){a.x - b.x, a.y - b.y};
    }
};
pos rec[N][5];
int ls[N], p[N];
inline db dist(pos a, pos b){
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
inline pos getFourth(int x){
    db ta = dist(rec[x][1], rec[x][2]);
    db tb = dist(rec[x][1], rec[x][3]);
    db tc = dist(rec[x][2], rec[x][3]);
    int a, b, c;
    if (fabs(ta * ta + tb * tb - tc * tc) <= EPS){
        a = 2, b = 3, c = 1;
    }else if (fabs(ta * ta + tc * tc - tb * tb) <= EPS){
        a = 1, b = 3, c = 2;
    }else if (fabs(tb * tb + tc * tc - ta * ta) <= EPS){
        a = 1, b = 2, c = 3;
    }
    return rec[x][a] - rec[x][c] + rec[x][b];
}
inline void addEdge(int &cnt, int x, int y, db w){
    cnt += 1; e[cnt] = (edge){x, y, w, ls[x]}; ls[x] = cnt;
    // printf("%d, %d, %.2f\n", x, y, w);
}
using std:: queue;
db dis[N];
int inQueue[N];
inline db min(db x, db y){
    return x<y?x:y;
}
inline db spfa(int st, int ed, int n){
    rep(i, 0, n * 4){
        dis[i] = INF;
    }
    queue<int> que;
    fill(inQueue, 0);
    st -= 1;
    rep(i, 1, 4){
        que.push(4 * st + i);
        inQueue[4 * st + i] = 1;
        dis[4 * st + i] = 0;
    }
    while (!que.empty()){
        int now = que.front(); que.pop();
        erg(i, now){
            if (dis[now] + e[i].w < dis[e[i].y]){
                dis[e[i].y] = dis[now] + e[i].w;
                if (!inQueue[e[i].y]){
                    inQueue[e[i].y] = 1;
                    que.push(e[i].y);
                }
            }
        }
        inQueue[now] = 0;
    }
    ed -= 1;
    db ret = INF;
    rep(i, 1, 4){
        ret = min(ret, dis[4 * ed + i]);
    }
    return ret;
}
int main(void){
    int T;
    scanf("%d", &T);
    while (T --){
        int n, t, st, ed;
        scanf("%d%d%d%d", &n, &t, &st, &ed);
        int edgeCnt = 0;
        fill(ls, 0);
        rep(i, 1, n){
            rep(j, 1, 3){
                scanf("%d%d", &rec[i][j].x, &rec[i][j].y);
            }
            rec[i][4] = getFourth(i);
            scanf("%d", &p[i]);
            // printf("%d %d\n", rec[i][4].x, rec[i][4].y);
            rep(j, 1, 4){
                rep(k, 1, 4){
                    addEdge(edgeCnt, (i - 1) * 4 + j, (i - 1) * 4 + k, p[i] * dist(rec[i][j], rec[i][k]));
                }
            }
        }
        rep(i, 1, n){
            rep(j, 1, n){
                rep(k, 1, 4){
                    rep(l, 1, 4){
                        addEdge(edgeCnt, (i - 1) * 4 + k, (j - 1) * 4 + l, t * dist(rec[i][k], rec[j][l]));
                    }
                }
            }
        }
        db ans = spfa(st, ed, n);
        printf("%.1f\n", ans);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值