Car的旅行路线

noip的原题,虽然思维量不大但是挺麻烦的。。。

原题链接:https://www.luogu.org/problemnew/show/P1027

本题的主要问题就是求每个城市第四个点的坐标。其余三点之间的连线中,一定有一条是对角线,所以不参与构成这条边的点,与第四个点的连线就是另一条对角线。平行四边形对角线相互评分,第四个点的坐标就求出来了。

然后就是按题意连边,连边之后做spfa即可,dij想必也可。a城市的每个点取到b城市四个点的最短花费,然后再在a城市的四个点中选一个最小值即可。

另外注意多组数据的清空与精度问题。

 

#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<iostream> 
using namespace std;
const int inf=1000000000.0;
int t,n,x[505],y[505],cnt;
int head[505],gm[505];
void read(int &y)
{
    y=0;char x=getchar();
    while(x<'0'||x>'9') x=getchar();
    while(x>='0'&&x<='9')
    {
        y=y*10+x-'0';
        x=getchar();
    }
}
struct edge
{
    int u,v; 
    double w;
}e[400005];
void add(int u,int v,double w)
{
    e[++cnt].u=head[u];
    e[cnt].v=v;
    e[cnt].w=w;
    head[u]=cnt;
}
double dis[505];
void spfa(int s)
{
    queue<int>q;
    for(int i=0;i<(n<<2);i++) dis[i]=inf;
    q.push(s);dis[s]=0;
    while(!q.empty())
    {
        int t=q.front();q.pop();
        for(int i=head[t];i;i=e[i].u)
        {
            int tmp=e[i].v;
            if(dis[tmp]>dis[t]+e[i].w)
            {
                dis[tmp]=dis[t]+e[i].w;
                q.push(tmp);
            }
        }
    }
}
double cw(int x,int y,int z,int w)
{
    return sqrt((x-z)*(x-z)+(y-w)*(y-w));
}
double min(double x,double y,double z,double w)
{
    double re=x;
    if(y<re) re=y;
    if(z<re) re=z;
    if(w<re) re=w;
    return re;
}
int main()
{
    read(t);
    while(t--)
    {
        memset(head,0,sizeof(head));cnt=0;
        int a,b,fm;
        read(n);read(fm);read(a);read(b);
        for(int i=0;i<n;i++)
        {
            int j=i*4;
            read(x[j+1]);read(y[j+1]);
            read(x[j+2]);read(y[j+2]);
            read(x[j+3]);read(y[j+3]);read(gm[i]);
            double w1=cw(x[j+1],y[j+1],x[j+2],y[j+2]);
            double w2=cw(x[j+1],y[j+1],x[j+3],y[j+3]);
            double w3=cw(x[j+2],y[j+2],x[j+3],y[j+3]);
            {
                if(w1>w2&&w1>w3){x[j]=x[j+1]+x[j+2]-x[j+3];y[j]=y[j+1]+y[j+2]-y[j+3];}
                if(w2>w1&&w2>w3){x[j]=x[j+1]+x[j+3]-x[j+2];y[j]=y[j+1]+y[j+3]-y[j+2];}
                if(w3>w1&&w3>w2){x[j]=x[j+3]+x[j+2]-x[j+1];y[j]=y[j+3]+y[j+2]-y[j+1];}
            }
        }
        for(int i=0;i<(n<<2);i++)
        {
            for(int j=0;j<(n<<2);j++)
            {
                if(i==j) continue;
                double lw=cw(x[i],y[i],x[j],y[j]);
                if((i>>2)==(j>>2)) add(i,j,gm[i>>2]*lw);
                else add(i,j,fm*lw);
            }
        }
        a<<=2,b<<=2;
        double s1,s2,s3,s4;
        spfa(a-4);s1=min(dis[b-4],dis[b-3],dis[b-2],dis[b-1]);
        spfa(a-3);s2=min(dis[b-4],dis[b-3],dis[b-2],dis[b-1]);
        spfa(a-2);s3=min(dis[b-4],dis[b-3],dis[b-2],dis[b-1]);
        spfa(a-1);s4=min(dis[b-4],dis[b-3],dis[b-2],dis[b-1]);
        printf("%.1lf\n",min(s1,s2,s3,s4));
    }
    return 0;
}

 

posted @ 2018-01-17 15:10  Excim  阅读(140)  评论(0编辑  收藏  举报