HDU 3622 Bomb Game(2-SAT + 二分)

【题目链接】

http://acm.hdu.edu.cn/showproblem.php?pid=3622


【题目大意】

要在坐标轴上放N次炸弹,每次可以选择两个位置中的一个位置放置,每个炸弹都可以控制它的爆炸范围(以放置位置为圆心的半径为r的圆圈),问半径最大可以多少,使得任意两个炸弹的爆炸范围都不重合。


【思路】

类似与poj 2296 , 但是判断重合的方法容易多了,果断1Y

注意精度问题。


【代码】

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#define SQ(x) ((x)*(x))
using namespace std;

const int MAXN = 110;
const int VN   = MAXN*2;
const int EN   = VN*VN*2;
const int INF  = 0x3f3f3f3f;
const double eps = 1e-9;
int n;
vector<int>g[VN];

struct Node{
    int x, y;
    void input(){scanf("%d%d",&x,&y);}
}arr[MAXN][2];

void init(){
    for(int i=0; i<2*n; ++i)
        g[i].clear();
}
void addEdge(int u, int v){
    g[u].push_back(v);
}

class Two_Sat{
public:
    bool check(){
        scc(); 
        for(int i=0; i<n; ++i)
            if(belong[i] == belong[i+n])
                return false;
        return true;
    }
private:
    void tarjan(const int u){
        int v;
        low[u] = dfn[u] = ++idx;
        sta[top++] = u;
        instack[u] = true;
        for(int i=0; i<g[u].size(); ++i){
            v = g[u][i];
            if(dfn[v] == -1){
                tarjan(v);
                low[u] = min(low[u], low[v]);
            }else if(instack[v]){
                low[u] = min(low[u], dfn[v]);
            }
        }
        if(low[u] == dfn[u]){
            ++bcnt;
            do{
                v = sta[--top];
                instack[v] = false;
                belong[v] = bcnt;
            }while(u != v);
        }
    }
    void scc(){
        idx=top=bcnt=0;
        memset(instack, 0, sizeof(instack));
        memset(dfn, -1, sizeof(dfn));
        for(int i=0; i<2*n; ++i)
            if(dfn[i] == -1)
                tarjan(i);
    }
private:
    int idx, top, bcnt;
    int low[VN], dfn[VN], belong[VN], sta[VN];
    bool instack[VN];
}sat;


double getDist(Node& a, Node& b){
    return  sqrt(SQ(a.x*1.0-b.x)+SQ(a.y*1.0-b.y));
}

void buildGraph(double r){
    init();
    for(int i=0; i<n; ++i){
        for(int j=i+1; j<n; ++j){
            if(2*r - getDist(arr[i][0], arr[j][0]) > eps) { //上, 上
                addEdge(i, j+n);
                addEdge(j, i+n);
            }
            if(2*r - getDist(arr[i][0], arr[j][1]) > eps) { //上, 下
                addEdge(i, j);
                addEdge(j+n, i+n);
            }
            if(2*r - getDist(arr[i][1], arr[j][0]) > eps){ // 下,上
                addEdge(i+n, j+n);
                addEdge(j, i);
            }
            if(2*r - getDist(arr[i][1], arr[j][1]) > eps){ // 下,下
                addEdge(i+n, j);
                addEdge(j+n, i);
            }
        }
    }
}

int main(){

    while(~scanf("%d", &n)){
    
        for(int i=0; i<n; ++i){
            arr[i][0].input();
            arr[i][1].input();
        }

        double l=0, r=20000, m, ans;

        while(r - l > eps){
            m = (r+l)/2.0;
            // 建图
            buildGraph(m);
            if(sat.check()){
                l = m+eps;
                ans = m;
            }
            else r=m;
        }
    
        printf("%.2f\n", ans);
    }


    return 0;
}


你可能感兴趣的:(HDU 3622 Bomb Game(2-SAT + 二分))