Car的旅行路线(NOIP2001)

版权声明:本文为博主原创文章,转载请注明出处:http://blog.csdn.net/cggwz https://blog.csdn.net/cggwz/article/details/81915792

白井黑子洛谷传送服务

白井黑子vijos传送服务

这里写图片描述

今天,是个重大一天,因为从今天起,为了大家有更好的体验,我将对我的题解进行全新改版!!
(不满的lovechq:你不就还有5天就去备战高考了吗?现在改版有啥用?
来自cgg的答复:虽然,在过几天,我会和大家依依不舍地道别,因为我真的要去备战高考了,但是明年暑假我会强势回归的!请各位放心)

知识点

(cgg解释:这里是为了让大家看到此题涉及的知识点,可以提前预习)

计算几何

向量,两点间距离公式

图论

邻接矩阵、Floyd(最短路)

基本思路

(cgg解释:这个版块是为了有些巨神准备的,因为巨神有时候只是一时短路,只要简单看看思路就可以了,所以在这里把思路简单整理一下,便于查看)

用数据结构去保存城市和点。
用向量求第四个点。
然后建图,算出每两个点之间的花费。
Floyd

详细解释

(cgg解释:这个版块是解释上面没有说清楚的地方)

保存城市和点

我们可以写两个结构体,一个是点,一个是城市。

计算第四个点

我们先来看看怎么计算第四个点。
我们可以先计算出来已知的三个点两两之间的距离,由于是矩形,我们一定有一个斜边,也就是矩形的对角线,也就是我们求出的三个距离中最长的那一个
那么接下来怎么处理呢?
我们来看一个图:
这里写图片描述

其中ABC三点已知。
我们观察向量BC和向量AD(你不知道向量?快戳开

因为四边形ABCD是矩形,所以向量BC和向量AD应该相等。
所以(x3-x2,y3-y2)=(x4-x1,y4-y1)
所以我们就可以求出来第四个点了:
x4=x3+x1-x2
y4=y3+y1-y2
这样就大功告成了!

建图计算距离

计算距离就用两点间距离公式

然后注意枚举顺序,依次计算出每一个点到同一个城市其他点的花费,再计算到其他城市每一个点的花费。
注意不只是距离,还要乘上每单位长度的花费。
用邻接矩阵就好了

Floyd

最简单的最短路算法,就不说了。
最后只要对起始和终点城市的每个飞机场之间的距离进行枚举,得到最小值即可。

难度点评

(cgg解释:客观地评价)

不是很难,没有什么思维难度,重在考察代码能力。

代码

(cgg解释:这显然是题解不可少的一部分)

!!!请注意:vijos的题目和洛谷的不一样
本处只提供洛谷的代码
vijos的题目没有多组数据,且保留两位小数

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath> 
using namespace std;
struct point{
    int num;
    int x,y;
};
struct city{
    point poi[5];
    int w;
};
int T;
int n,t,A,B;
city c[105];
int ind;
double mapp[405][405];
double dis(point poi1,point poi2){
    return sqrt((poi1.x-poi2.x)*(poi1.x-poi2.x)+(poi1.y-poi2.y)*(poi1.y-poi2.y));
}
void getpoi4(city& ci){
    double l12=dis(ci.poi[1],ci.poi[2]),l13=dis(ci.poi[1],ci.poi[3]),l23=dis(ci.poi[2],ci.poi[3]);
    if(l12>l13&&l12>l23){
        ci.poi[4].x=ci.poi[1].x+ci.poi[2].x-ci.poi[3].x;
        ci.poi[4].y=ci.poi[1].y+ci.poi[2].y-ci.poi[3].y;
    }else if(l13>l12&&l13>l23){
        ci.poi[4].x=ci.poi[1].x+ci.poi[3].x-ci.poi[2].x;
        ci.poi[4].y=ci.poi[1].y+ci.poi[3].y-ci.poi[2].y;
    }else{
        ci.poi[4].x=ci.poi[3].x+ci.poi[2].x-ci.poi[1].x;
        ci.poi[4].y=ci.poi[3].y+ci.poi[2].y-ci.poi[1].y;
    }
}
int main(){
    scanf("%d",&T);
    ind=1;
    while(T--){
        memset(mapp,0x42,sizeof(mapp));
        scanf("%d%d%d%d",&n,&t,&A,&B);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d%d%d%d%d",&c[i].poi[1].x,&c[i].poi[1].y,&c[i].poi[2].x,&c[i].poi[2].y,&c[i].poi[3].x,&c[i].poi[3].y,&c[i].w);
            getpoi4(c[i]);
            c[i].poi[1].num=ind++;
            c[i].poi[2].num=ind++;
            c[i].poi[3].num=ind++;
            c[i].poi[4].num=ind++;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=4;j++){
                point cur=c[i].poi[j];
                for(int k=j+1;k<=4;k++){
                    point kkk=c[i].poi[k];
                    mapp[cur.num][kkk.num]=mapp[kkk.num][cur.num]=dis(cur,kkk)*(double)c[i].w;
                }
                for(int k=i+1;k<=n;k++){
                    for(int l=1;l<=4;l++){
                        point kkk=c[k].poi[l];
                        mapp[cur.num][kkk.num]=mapp[kkk.num][cur.num]=dis(cur,kkk)*(double)t;
                    }
                }
            }
        }
        for(int k=1;k<ind;k++){
            for(int i=1;i<ind;i++){
                for(int j=1;j<ind;j++){
                    if(i==j){
                        mapp[i][j]=0.0;
                        continue;
                    }
                    mapp[i][j]=min(mapp[i][j],mapp[i][k]+mapp[k][j]);
                }
            }
        }
        double ans=100000000000.0;
        for(int i=1;i<=4;i++){
            for(int j=1;j<=4;j++){
                ans=min(ans,mapp[c[A].poi[i].num][c[B].poi[j].num]);
            }
        }
        printf("%.1lf\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/cggwz/article/details/81915792
今日推荐