洛谷 Car的旅行路线 p1027 spfa

时间限制: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));
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值