JZOJ 5401. 【NOIP2017提高A组模拟10.8】Star Way To Heaven

来源:互联网 发布:工业机器人控制算法 编辑:程序博客网 时间:2024/06/14 10:25

题目

这里写图片描述

题解

这题可以二分,设答案为mid,将问题转化为纵坐标为[mid,m-mid]之间的,点变成半径为mid的圆,看上面是否能连到下面。
80分:并查集做法。(然而我是这么做的,我直接存储该圆与哪一边连通,如果一个圆既与上面连通,又与下面连通,那么mid过大,我不知道这么做为什么是错的,有大佬帮我看看为什么吗?我WA了3个点)(第一份代码是WA了的代码)
100分做法:不二分,考虑连最小生成树。k+2个点,但是很多条边。所以用Prim算法。然后答案即为k+1到k+2的路径上最长边/2。
Prim算法:设Dis[i]表示目前没有被选的点i与任何一个被选的点的最小距离。
然后每一次挑选一个Dis最小的点作为下一个被选的点。

AC代码

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 1000010#define eps 0.0000005#define DB double#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;struct point{    DB x,y; };point pt[N];int n,m,k;int i,j;DB l,r,l1,r1,mid,ans,temp;int bel[N];bool jie;bool cmp(point a,point b){    return a.y<b.y || (a.y==b.y && a.x<b.x);}DB dis(DB X1,DB Y1,DB X2,DB Y2){    return sqrt((X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2));}int main(){    freopen("starway.in","r",stdin);    freopen("starway.out","w",stdout);    scanf("%d%d%d",&n,&m,&k);    fo(i,1,k)scanf("%lf%lf",&pt[i].x,&pt[i].y);    sort(pt+1,pt+k+1,cmp);    ans=0;    l=0,r=(DB)m/2;    while(l<=r){        mid=(l+r)/2;        l1=mid;r1=m-mid;        memset(bel,0,sizeof(bel));        fo(i,1,k)            if(pt[i].y<=l1+mid) bel[i]=1;else break;        fd(i,k,1)            if(pt[i].y>=r1-mid) bel[i]=2;else break;        jie=0;        fo(i,1,k-1){            if(bel[i]==1){                fo(j,i+1,k){                    temp=dis(pt[i].x,pt[i].y,pt[j].x,pt[j].y);                    if(temp<=2*mid){                        if(bel[j]==2){                            jie=1;                            break;                        }                        bel[j]=1;                    }                }            }            if(jie)break;        }        if(jie)r=mid-eps;else ans=mid,l=mid+eps;    }    printf("%.8lf",ans);    return 0;}
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 6010#define eps 0.000001#define DB double#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;struct point{    DB x,y;};point pt[N];struct note{    int to,next;    DB val;};note edge[N*2];int n,m,k,tot;int i,j,gx,gy,wz,x;DB l,r,l1,r1,mid,ans,mx,temp;DB a1,a2,a3,a4;int a[N][5],f[N];DB dis[N];int head[N],pre[N];bool jie[N],vis[N],p;int read(){    int res=0,fh=1;char ch;    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();    if(ch=='-')fh=-1,ch=getchar();    while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar();    return res;}void lb(int x,int y,DB z){    edge[++tot].to=y;    edge[tot].next=head[x];    edge[tot].val=z;    head[x]=tot;}DB getdis(int a,int b){    if(a>b)swap(a,b);    if(a==k+1&&b==k+2)return m;    if(b==k+1)return pt[a].y;    if(b==k+2)return m-pt[a].y;    return sqrt((pt[a].x-pt[b].x)*(pt[a].x-pt[b].x)+(pt[a].y-pt[b].y)*(pt[a].y-pt[b].y));}int get(int x){return(f[x]==x)?x:f[x]=get(f[x]);}void dg(int x,int fa,DB v){    if(x==k+2){        ans=v;        return;    }    int i;    for(i=head[x];i;i=edge[i].next)        if(edge[i].to!=fa)dg(edge[i].to,x,max(v,edge[i].val));}int main(){    freopen("starway.in","r",stdin);    freopen("starway.out","w",stdout);    n=read();m=read();k=read();    fo(i,1,k){        gx=read();gy=read();        pt[i].x=(DB)gx;pt[i].y=(DB)gy;    }    ans=0;    memset(dis,127,sizeof(dis));    dis[k+1]=0;    fo(i,1,k+2){        wz=0,mx=2147483647;        fo(j,1,k+2)            if(dis[j]<mx && !vis[j])mx=dis[j],wz=j;        if(pre[wz])lb(pre[wz],wz,dis[wz]),lb(wz,pre[wz],dis[wz]);        vis[wz]=1;        fo(j,1,k+2)            if(!vis[j] && wz!=j){                temp=getdis(wz,j);                if(temp<dis[j])dis[j]=temp,pre[j]=wz;            }    }    dg(k+1,0,0);    ans/=2;    printf("%.8lf",ans);    return 0;}
阅读全文
1 0
原创粉丝点击