思路:
這個題目預處理起來比較麻煩,由於題目中說了一個城市有四個機場,但是指給定三個,所以需要我們自己去求第四個點,這個過程就需要枚舉哪一個點爲直角頂點然後再求第四個。求出第四個點後在預處理出任意兩個機場之間的花費(注意區分同一個城市和不同城市),然後再跑dij即可.
求第四個點只需枚舉一下哪個點所對應的邊爲斜邊在通過斜率計算即可
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e2+5;
int s,t,A,B;
struct node
{
int x[5];
int y[5];
}a[maxn];
double mp[maxn << 2][maxn << 2],ans;
int cal(int id)
{
return ((id - 1) << 2) + 1;
}
double dis(int x1,int y1,int x2,int y2)
{
return sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
}
void get(int cur,int ti)
{
int x[5],y[5];
memcpy(x,a[cur].x,sizeof x);
memcpy(y,a[cur].y,sizeof y);
double d0 = dis(x[0],y[0],x[1],y[1]);
double d1 = dis(x[0],y[0],x[2],y[2]);
double d2 = dis(x[1],y[1],x[2],y[2]);
double mx = max(d0,max(d2,d1));
if(mx == d0)
{
a[cur].x[3] = x[0] + x[1] - x[2];
a[cur].y[3] = y[0] + y[1] - y[2];
}
else if(mx == d1)
{
a[cur].x[3] = x[0] - x[1] + x[2];
a[cur].y[3] = y[0] - y[1] + y[2];
}
else
{
a[cur].x[3] = -x[0] + x[1] + x[2];
a[cur].y[3] = -y[0] + y[1] + y[2];
}
for(int i = 0;i < 4;++i)
for(int j = i+1;j < 4;++j)
{
int pos = cal(cur);
mp[pos + i][pos + j] = mp[pos + j][pos + i]
= dis(a[cur].x[i],a[cur].y[i],a[cur].x[j],a[cur].y[j])*ti;
}
}
void dij(int sta)
{
bool vis[maxn << 2];
double dis[maxn << 2];
for(int i = 0;i <= s;++i)
{
dis[i] = inf;
vis[i] = 0;
}
dis[sta] = 0;
for(int i = 1;i <= s;++i)
{
double mi = inf;
int u = -1;
for(int j = 1;j <= s;++j)
{
if(!vis[j] && mi > dis[j])
{
u = j;
mi = dis[j];
}
}
if(u != -1)
vis[u] = 1;
for(int j = 1;j <= s;++j)
{
if(dis[j] > dis[u] + mp[u][j])
dis[j] = dis[u] + mp[u][j];
}
}
int p = cal(B);
for(int j = 0;j < 4;++j)
{
if(ans > dis[p + j])
ans = dis[p + j];
//printf("%f\n",dis[B+j]);
}
return ;
}
int main()
{
int _;
cin >> _;
while(_--)
{
scanf("%d %d %d %d",&s,&t,&A,&B);
if(A == B)
{
puts("0.0");
return 0;
}
for(int i = 0;i <= s;++i)
for(int j = 0;j <= s;++j)
mp[i][j] = mp[j][i] = inf;
for(int i = 1;i <= s;++i)
{
int ti;
scanf("%d %d %d %d %d %d %d",&a[i].x[0],&a[i].y[0],&a[i].x[1],
&a[i].y[1],&a[i].x[2],&a[i].y[2],&ti);
get(i,ti);
//puts("***");
}
for(int i = 1;i <= s;++i)
{
int pos1 = cal(i);
for(int j = 1;j <= s;++j)
{
int pos2 = cal(j);
if(i == j) continue;
for(int k = 0;k < 4;++k)
{
for(int c = 0;c < 4;++c)
{
mp[pos1 + k][pos2 + c] = mp[pos2 + c][pos1 + k]
= dis(a[i].x[k],a[i].y[k],a[j].x[c],a[j].y[c])*t;
}
}
}
}
s <<= 2;
ans = inf;
A = cal(A);
for(int i = 0;i < 4;++i)
{
dij(A + i);
}
printf("%.1f\n",ans);
}
return 0;
}