HDU - 3156 Repair Depots (Dacning Links 重复覆盖+二分+计算几何)

题意:

给定n个机器人的坐标,让确定m个维修点的坐标,使得机器人到离他最近的维修点的最大距离最小化。

分析:

这道题目于以往不一样的地方在于以往的是m个点在n个点上,所以直接建图就可以的。但是这道题让自己确定m个点。所以采用的解决方法是二分枚举圆的半径,从而确定圆心,再根据圆心判断每个圆心能到达哪些点。但是要注意去重,因为很多时候这个圆能覆盖到的是另一个圆能覆盖到的子集。

#include<bits/stdc++.h>

using namespace std;

const int maxn=1005;
const int maxm=1005;
const int maxnode=maxn*maxm;
const int inf=0x3f3f3f3f;

int N,M;

struct DLX{
    int n,m,size;
    int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
    int H[maxn],S[maxm];
    int ansd,ans[maxn];
    void init(int _n,int _m){
        n=_n;
        m=_m;
        for(int i=0;i<=m;i++){
            S[i]=0;
            U[i]=D[i]=i;
            L[i]=i-1;
            R[i]=i+1;
        }
        R[m]=0;L[0]=m;
        size=m;
        for(int i=1;i<=n;i++){
            H[i]=-1;
        }
    }
    void Link(int r,int c){
        ++S[Col[++size]=c];
        Row[size]=r;
        D[size]=D[c];
        U[D[c]]=size;
        U[size]=c;
        D[c]=size;
        if(H[r]<0) H[r]=L[size]=R[size]=size;
        else{
            R[size]=R[H[r]];
            L[R[H[r]]]=size;
            L[size]=H[r];
            R[H[r]]=size;
        }
    }
    void remove(int c){
        for(int i=D[c];i!=c;i=D[i]){
            L[R[i]]=L[i];
            R[L[i]]=R[i];
        }
    }
    void resume(int c){
        for(int i=U[c];i!=c;i=U[i]){
            L[R[i]]=R[L[i]]=i;
        }
    }
    bool v[maxm];
    int f(){
        int ret=0;
        for(int c=R[0];c!=0;c=R[c]) v[c]=1;
        for(int c=R[0];c!=0;c=R[c]){
            if(v[c]){
                ret++;
                v[c]=false;
                for(int i=D[c];i!=c;i=D[i]){
                    for(int j=R[i];j!=i;j=R[j]){
                        v[Col[j]]=false;
                    }
                }
            }
        }
        return ret;
    }
    bool dance(int d){
        if(d+f()>M) return false;
        if(R[0]==0){
            return d<=M;
        }
        int c=R[0];
        for(int i=R[0];i!=0;i=R[i]){
            if(S[i]<S[c]){
                c=i;
            }
        }
        for(int i=D[c];i!=c;i=D[i]){
            remove(i);
            for(int j=R[i];j!=i;j=R[j]) remove(j);
            if(dance(d+1)) return true;
            for(int j=L[i];j!=i;j=L[j]) resume(j);
            resume(i);
        }
        return false;
    }
}dlx;

struct point{
    double x,y;
    point(){}
    point(double x,double y):x(x),y(y){}
    point operator - (const point p){ return point(x-p.x,y-p.y); }
    point operator + (const point p){ return point(x+p.x,y+p.y); }
    point operator * (double s){ return point(x*s,y*s); }
    point operator / (double s){ return point(x/s,y/s); }
    double _distance(){ return x*x+y*y; }
}pt[20],center[550];

double distance(point &a,point &b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double dis[20][20];

const double eps=1e-8;

int cmp(double x){
    if(fabs(x)<eps) return 0;
    if(x>0) return 1;
    return -1;
}

void mark(point p1,point p2,double d,double r,int &cnt){
    if(cmp(d)==0){
        center[++cnt]=p1;
        return ;
    }
    point p0=(p1+p2)/2;
    if(cmp(d-2*r)==0) center[++cnt]=p0;
    if(cmp(d-2*r)==-1){
        point p=(p2-p1)/d,v=point(p.y,-p.x);
        p=p*d/2;
        v=v*sqrt(r*r-p._distance());
        center[++cnt]=p0+v;
        center[++cnt]=p0-v;
    }
}

int ST[550],vis[550];

bool judge(double mid){
    int cnt=0;
    for(int i=1;i<=N;i++){
        for(int j=1;j<=N;j++){
            mark(pt[i],pt[j],dis[i][j],mid,cnt);
        }
    }
    dlx.init(cnt,N);
    double r=mid*mid;
    memset(vis,0,sizeof vis);
    memset(ST,0,sizeof ST);
    for(int i=1;i<=cnt;i++){
        for(int j=1;j<=N;j++){
            if(cmp((center[i]-pt[j])._distance()-r)<=0) ST[i]|=(1<<j);
        }
    }
    for(int i=1;i<=cnt;i++){
        if(vis[i]==0){
            for(int j=i+1;j<=cnt;j++){
                if((ST[i]|ST[j])==ST[j]){
                    vis[i]=1;
                    break;
                }
                if((ST[i]|ST[j])==ST[i]){
                    vis[j]=1;
                }
            }
        }
    }
    for(int i=1;i<=cnt;i++){
        for(int j=1;vis[i]==0&&j<=N;j++){
            if(ST[i]&(1<<j)) dlx.Link(i,j);
        }
    }
    return dlx.dance(0);
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&N,&M);
        for(int i=1;i<=N;i++){
            scanf("%lf%lf",&pt[i].x,&pt[i].y);
        }
        for(int i=1;i<=N;i++){
            for(int j=1;j<=N;j++){
                dis[i][j]=distance(pt[i],pt[j]);
            }
        }
        double l=0.0,r=15.0;
        while(cmp(r-l)==1){
            double mid=(l+r)/2;
            if(judge(mid)) r=mid;
            else l=mid;
        }
        printf("%.6f\n",r);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问题,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警中心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥中心基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值