【最短路】公路修建

本题重点是对于第二条规则的理解:

如图,对于任意一点A,因为它申请修建AB道路,因此离A最近的点一定是B

同理,B申请修建BC道路,因此C一定比A离B更近(即C在圆B内,不包含边界)

同时,C申请修建CA道路,即A离C比A离B更近

满足题意的话,ABC只能组成正三角形,因此排除最短边有三种情况

因为题目有:

一个实数,四舍五入保留两位小数,表示公路总长。(保证有惟一解)

因此我们可以得出结论:

规则2是没有用的

于是,题目的第一条规则

如果两个或以上城市申请修建同一条公路,则让它们共同修建

明显是最小生成树,裸的板子

for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++) if(!vis[j]&&dis[j]<MIN) MIN=dis[j],pos=j;
        ans+=MIN; vis[pos]=1;MIN=oo;
        for (int j=1;j<=n;j++) dis[j]=min(dis[j],Distance(pos,j));
    }

再有,由于坐标范围很大,因此直接用函数求出距离即可

double Distance(int a,int b)
{return sqrt((double)(point[a].x-point[b].x)*(point[a].x-point[b].x)+
             (double)(point[a].y-point[b].y)*(point[a].y-point[b].y));
}

于是就可以得出代码= =

#include<bits/stdc++.h>
#define oo 99999999
using namespace std;

int n,pos;
bool vis[5005];
double ans,MIN=oo,dis[5005];
struct tqr{int x,y;}point[5005];

double Distance(int a,int b){return sqrt((double)(point[a].x-point[b].x)*(point[a].x-point[b].x)+(double)(point[a].y-point[b].y)*(point[a].y-point[b].y));}

template<class T> inline void read(T &re){re=0;T sign=1;char tmp;while((tmp=getchar())&&(tmp<'0'||tmp>'9')) if(tmp=='-') sign=-1;re=tmp-'0';while((tmp=getchar())&&(tmp>='0'&&tmp<='9')) re=re*10+(tmp-'0');re*=sign;}

int main()
{
    // freopen("road.in","r",stdin);
    // freopen("road.out","w",stdout);
    read(n);
    for (int i=1;i<=n;i++){read(point[i].x);read(point[i].y);dis[i]=oo;}//读入和初始化
    dis[1]=0;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++) if(!vis[j]&&dis[j]<MIN) MIN=dis[j],pos=j;
        ans+=MIN; vis[pos]=1;MIN=oo;
        for (int j=1;j<=n;j++) dis[j]=min(dis[j],Distance(pos,j));
    }
    printf("%.2lf\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/tqr06/p/10458908.html