HDU 3622 Bomb Game

题意:给你n个炸弹,每个炸弹都有两个位置放置,问你最大的爆炸半径,使得任意两个炸弹的爆炸范围不相交,可以相切,问半径是多少

思路:对半径进行二分,很显然是单调的,所以满足条件,然后由于点数不是很多,每次n2暴力建图跑sat

代码:(忘记跑tarjan对着空气debug半小时)

#include <bits/stdc++.h>
using namespace std;
const int maxn=1005;
const int maxm=2000005;
const double eps=1e-4;

struct point
{
    double x,y;
}p[1005];
struct node
{
    int to,nxt;
} edge[maxm];
int head[maxn];
int low[maxn],dfn[maxn],stk[maxn],be[maxn];
int top,tim,num,tot;/// init -1 0 0 0
bool instk[maxn];

void add_edge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].nxt=head[u];
    head[u]=tot++;
}
void init()
{
    tot=0;num=0;tim=0;
    top=-1;
    memset(dfn,0,sizeof(dfn));
    memset(head,-1,sizeof(head));
    memset(instk,false,sizeof(instk));
}
void tarjan(int u)
{
    int v;
    low[u]=dfn[u]=++tim;
    stk[++top]=u;
    instk[u]=1;
    for(int k=head[u];~k;k=edge[k].nxt){
        v=edge[k].to;
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(instk[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u]){
        ++num;
        do{
            v=stk[top--];
            instk[v]=false;
            be[v]=num;
        }
        while(u!=v);
    }
}
double dist(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int n;
void build(double x)
{
//    printf("asd %d\n",n*2);
    for(int i=0;i<2*n;i++){
        for(int j=0;j<2*n;j++){
            if((i/2!=j/2)&&(dist(p[i],p[j])<x)){
                add_edge(i,j^1);
                add_edge(j,i^1);
//                printf("fuck %d %d %d %d\n",i,j^1,j,i^1);
            }
        }
    }
}
bool check(double x)
{
    init();
    build(x*2.0);
    for(int i=0;i<2*n;i++){
        if(!dfn[i])tarjan(i);
    }
    bool ok=true;
    for(int i=0;i<2*n;i+=2){
        if(be[i]==be[i^1]){
            ok=false;break;
        }
    }
    return ok;
}
int main()
{
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++){
            scanf("%lf%lf%lf%lf",&p[i*2].x,&p[i*2].y,&p[i*2+1].x,&p[i*2+1].y);
        }
//        printf("test %d\n",check(1.0));
        double L=0.0,R=9999999.0;
        while(L+eps<R){
            double mid=(L+R)*0.5;
            if(check(mid)){
                L=mid;
            }
            else R=mid;
        }
        printf("%.2f\n",L);
    }
    return 0;
}

 

posted @ 2018-11-09 19:52  啦啦啦天啦噜  阅读(203)  评论(0编辑  收藏  举报