时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。
图例(从上而下)
机场
高速铁路
飞机航线
注意:图中并没有标出所有的铁路与航线。
那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
任务:找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入描述:
第一行为一个正整数n( 0 ≤ n ≤ 10 ),表示有n组测试数据。
每组的第一行有4个正整数S,t,A,B。
S( 0 < S ≤ 100 )表示城市的个数,t表示飞机单位里程的价格,A,B分别为城市A,B的序号,( 1 ≤ A,B ≤ S )。
接下来有S行,其中第i行均有7个正整数 xi1,yi1,xi2,yi2,xi3,yi3,Ti 这当中的(xi1,yi1),(xi2,yi2),(xi3,yi3)分别是第i个城市中任意3个机场的坐标,Ti 为第i个城市高速铁路单位里程的价格。
输出描述:
共有n行,每行1个数据对应测试数据(最小花费)。保留一位小数。
示例1
输入
复制
1
3 10 1 3
1 1 1 3 3 1 30
2 5 7 4 5 2 1
8 6 8 8 11 6 3
输出
复制
47.5
题解:这题想吐,debug了1个半小时,最后发现spfa带进去的参数手抖把2写成21,居然过了3个点。
一开始我跑的是dfs,t了一个点,可以再试下。
主要就是要求第四个点,这里通过向量求解,然后注意有4个起点个4个终点,同一个机场个不同机场之间走价格不同,最后跑一边spfa 把4个终点的值比较出最小值即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 105;
int n,s,t,cnt,vis[4*maxn],m[maxn],v;
struct edge{
double x,y;
int id; //存属于哪一个机场
}e[4*maxn];
int check(edge x1,edge x2,edge x3){ //判断是否是直角点
int t = (x2.x-x1.x)*(x3.x-x1.x)+(x2.y-x1.y)*(x3.y-x1.y);
if(!t) return 1;
return 0;
}
edge cal(edge x1,edge x2,edge x3){ // 计算出第4个点
edge tmp;
tmp.x = x2.x + x3.x - x1.x;
tmp.y = x2.y + x3.y - x1.y;
return tmp;
}
double distant(double nx,double ny,double mx,double my){ //计算两点间距离
return sqrt((nx-mx)*(nx-mx)+(ny-my)*(ny-my));
}
double spfa(int s1,int s2,int s3,int s4){
double dp[4*maxn];
queue<int>q;
for(int i=0;i<=cnt;i++) dp[i]=1e9;
dp[s1]=dp[s2]=dp[s3]=dp[s4]=0; //4个起点
q.push(s1),q.push(s2),q.push(s3),q.push(s4);
vis[s1]=vis[s2]=vis[s3]=vis[s4]=1;
while(!q.empty()){ //spfa板子
int k = q.front();q.pop();
vis[k]=0;
for(int i=1;i<=cnt;i++){
int p;
double d = distant(e[k].x,e[k].y,e[i].x,e[i].y); //判断是属于同一机场
if(e[k].id==e[i].id) p=m[e[k].id];
else p=v;
if(dp[k]+d*p<dp[i]){
dp[i]=dp[k]+d*p;
if(!vis[i]) q.push(i),vis[i]=1;
}
}
}
int t1 =(t-1)*4+1, t2=(t-1)*4+2,t3=(t-1)*4+3, t4=t*4;
// printf("%.1f %.1f %.1f %.1f\n",dp[t1],dp[t2],dp[t3],dp[t4]);
return min(dp[t1],min(dp[t2],min(dp[t3],dp[t4])));
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d",&n,&v,&s,&t);
cnt = 0;
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++){
edge x1,x2,x3,x4;
scanf("%lf%lf%lf%lf%lf%lf%d",&x1.x,&x1.y,&x2.x,&x2.y,&x3.x,&x3.y,&m[i]);
if(check(x1,x2,x3)) x4=cal(x1,x2,x3);
else if(check(x2,x1,x3)) x4=cal(x2,x1,x3);
else x4=cal(x3,x1,x2);
x1.id=x2.id=x3.id=x4.id=i; //属于那个机场
e[++cnt]=x1,e[++cnt]=x2,e[++cnt]=x3,e[++cnt]=x4;
}
// for(int i=1;i<=cnt;i++)
// printf("%d %d\n",e[i].x,e[i].y);
printf("%.1lf\n",spfa((s-1)*4+1,(s-1)*4+2,(s-1)*4+3,s*4));
}
}