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;
}