题目来源:
题目描述:
题目描述
又到暑假了,住在城市 AA 的 CarCar 想和朋友一起去城市 BB 旅游。她知道每个城市都有 44 个飞机场,分别位于一个矩形的 44 个顶点上,同一个城市中 22 个机场之间有 11 条笔直的高速铁路,第 II 个城市中高速铁路了的单位里程价格为 T_iTi ,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为 tt 。
图例(从上而下)
机场
高速铁路
飞机航线
注意:图中并没有标出所有的铁路与航线。
那么 CarCar 应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
找出一条从城市 AA 到 BB 的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入输出格式
输入格式:第一行为一个正整数 nn ( 0 \le n \le 100≤n≤10 ),表示有 nn 组测试数据。
每组的第一行有 44 个正整数 s,t,A,Bs,t,A,B 。
SS ( 0<S \le 1000<S≤100 )表示城市的个数, tt 表示飞机单位里程的价格, AA , BB 分别为城市 AA , BB 的序号,( 1 \le A1≤A, B \le SB≤S )。
接下来有 SS 行,其中第 II 行均有 77 个正整数 xi_1,yi_1,xi_2,yi_2,xi_3,yi_3,Tixi1,yi1,xi2,yi2,xi3,yi3,Ti ,这当中的( xi_1,yi_1xi1,yi1 ),( xi_2,yi_2xi2,yi2),( xi_3,yi_3xi3,yi3 )分别是第 ii 个城市中任意 33 个机场的坐标, TiTi 为第 ii 个城市高速铁路单位里程的价格。
输出格式:共有 nn 行,每行 11 个数据对应测试数据。 保留一位小数。
输入输出样例
解题思路:
这题是一个最短路的裸题,关键还是怎样把所有边存起来,首先是它只输入每个城市的3个点,所以要先把第三个点算出来,可以用x,y的偏移量算。接下来就是存边,因为高速和航线的价格不同,所以要分开储存。存完之后就可以用spfa,因为求得是两个城市之间的距离,所以我用了4次spfa,分别储存起点机场到终点机场的距离,机场编号我是1-4,5-8。。这样存的,最后算出所有距离的最小值就行。
代码:
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
double min(double x,double y)
{
if(x>y)return y;
return x;
}
struct newt{
int dian[5][2];
int fy;
}cs[1005];
bool vis[100000];
double dis[4][100000];
vector<pair<int,double> >E[1000005];
queue<int>q;
double js(int x1,int y1,int x2,int y2)//计算距离
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
void xz(int id,int x1,int y1,int x2,int y2,int x3,int y3)//已知3点求第四个点
{
int x4,y4;
if((x1-x2)*(x2-x3)+(y1-y2)*(y2-y3)==0){
x4=x1-x2+x3;
y4=y1-y2+y3;
cs[id].dian[4][0]=x4;
cs[id].dian[4][1]=y4;
}
else if((x1-x2)*(x1-x3)+(y1-y2)*(y1-y3)==0){
x4=x2-x1+x3;
y4=y2-y1+y3;
cs[id].dian[4][0]=x4;
cs[id].dian[4][1]=y4;
}
else{
x4=x1-x3+x2;
y4=y1-y3+y2;
cs[id].dian[4][0]=x4;
cs[id].dian[4][1]=y4;
}
return ;
}
int main()
{
int t;
cin>>t;
while(t--){
int n,cost,X,Y;
cin>>n>>cost>>X>>Y;
for(int i=1;i<=n;i++)
{
int a,b,c,d,e,f;
cin>>a>>b>>c>>d>>e>>f>>cs[i].fy;
cs[i].dian[1][0]=a;
cs[i].dian[1][1]=b;
cs[i].dian[2][0]=c;
cs[i].dian[2][1]=d;
cs[i].dian[3][0]=e;
cs[i].dian[3][1]=f;
xz(i,a,b,c,d,e,f);
for(int j=1;j<=3;j++)
for(int k=j+1;k<=4;k++)//每个城市内的边
{
double jl=js(cs[i].dian[j][0],cs[i].dian[j][1],cs[i].dian[k][0],cs[i].dian[k][1])*cs[i].fy;
E[j+(i-1)*4].push_back(make_pair(k+(i-1)*4,jl));
E[k+(i-1)*4].push_back(make_pair(j+(i-1)*4,jl));
}
}
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)//每两个城市之间的边
{
for(int k=1;k<=4;k++)
for(int s=1;s<=4;s++)
{
//cout<<k+(i-1)*4<<" "<<s+(j-1)*4<<endl;
double jl=js(cs[i].dian[k][0],cs[i].dian[k][1],cs[j].dian[s][0],cs[j].dian[s][1])*cost;
E[k+(i-1)*4].push_back(make_pair(s+(j-1)*4,jl));
E[s+(j-1)*4].push_back(make_pair(k+(i-1)*4,jl));
}
}
// for(int i=1;i<=n*4;i++)
// for(int j=0;j<E[i].size();j++)
// cout<<i<<" "<<E[i][j].first<<" "<<E[i][j].second<<endl;
int qd[4];
for(int i=0;i<4;i++)
for(int j=0;j<=10000;j++)
dis[i][j]=1e9;
for(int i=0;i<4;i++)
qd[i]=(X-1)*4+(i+1);
for(int i=0;i<4;i++)
{
memset(vis,0,sizeof(vis));
q.push(qd[i]);
vis[qd[i]]=1;
dis[i][qd[i]]=0;
while(!q.empty())
{
int now=q.front();q.pop();
vis[now]=0;
for(int j=0;j<E[now].size();j++)
{
int v=E[now][j].first;
//cout<<dis[i][v]<<" "<<dis[i][now]<<" "<<E[now][j].second<<endl;
if(dis[i][v]>dis[i][now]+E[now][j].second)
{
dis[i][v]=dis[i][now]+E[now][j].second;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
// for(int j=1;j<=n*4;j++)
// cout<<dis[i][j]<<" ";
// cout<<endl;
}
double Min=1e9;
for(int i=0;i<4;i++)
{
for(int j=(Y-1)*4+1;j<=(Y-1)*4+4;j++)
{
//cout<<i<<" "<<j<<" "<<dis[i][j]<<endl;
if(dis[i][j]<Min){
Min=dis[i][j];
}
}
}
printf("%.1lf\n",Min);
}
return 0;
}