hdu 3622 Bomb Game

来源:互联网 发布:东芝2303am网络扫描 编辑:程序博客网 时间:2024/06/05 20:06

Bomb Game


很裸的2-sat。二分枚举半径,然后对于每个点i枚举j,其中j不是i'.如果dist(i,j)小于半径,那么就连边i->j', j->i',然后判断是否出现冲突。由于用double的话会出现精度误差,而给定点的坐标都是整数.所以,我们可以将其转化为整型处理,不进行开方操作,而比较的时候也是枚举两点间的距离。最后输出答案的时候在开方就行了。


/*    author    : csuchenan    prog      : hdu 3622    algorithm : 2-sat*/#include <cstdio>#include <cstring>#include <vector>#include <cmath>using std::vector;const int maxn= 100;double eps = 1e-5;vector<int> G[maxn*2+10];struct Point{    int x , y;}point[maxn*2+10];int d[maxn<<1][maxn<<1];int dfn[maxn*2+10];int low[maxn*2+10];int col[maxn*2+10];int stack[maxn*2+10];bool ins[maxn*2+10];int depth, top, color;int n;int dist(Point &a, Point &b){    return (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y);}int min(int x, int y){    if(x < y)        return x;    return y;}void predour(){    memset(d, 0, sizeof(d));    for(int i = 0; i < 2*n; i ++){        for(int j = 0; j < 2*n ; j ++){            d[i][j] = dist(point[i], point[j]);        }    }}void init(){    memset(dfn, 0, sizeof(dfn));    memset(ins, 0, sizeof(ins));    memset(col, 0, sizeof(col));    top = color = depth = 0;    for(int i = 0; i < n*2; i ++){        G[i].clear();    }}void add_edge(int i, int j){    G[i].push_back(j);}void tarjan(int v){    dfn[v] = low[v] = ++ depth;    ins[v] = true;    stack[top ++] = v ;    for(int i = 0; i != G[v].size(); i ++){        int u = G[v][i];        if(dfn[u]==0){            tarjan(u);            low[v] = min(low[v], low[u]);        }        else if(ins[u]){            low[v] = min(low[v], dfn[u]);        }    }    if(low[v]==dfn[v]){        int k;        color++;        do{            k = stack[--top];            ins[k] = false;            col[k] = color;        }while(k!=v);    }}bool two_sat(){    //tarjan    for(int i = 0; i < 2*n; i ++){        if(dfn[i]==0){            tarjan(i);        }    }    //check    for(int i = 0; i < n; i ++){        if(col[i<<1] == col[i<<1|1]){            return false;        }    }    return true;}bool test(int R){    init();//建图前先初始化    //建图    for(int i = 0; i < n; i ++){        for(int j = i+1; j < n; j ++){            if(d[i<<1][j<<1] < R){                add_edge(i<<1, j<<1|1);                add_edge(j<<1, i<<1|1);            }            if(d[i<<1|1][j<<1] < R){                add_edge(i<<1|1, j<<1|1);                add_edge(j<<1, i<<1);            }            if(d[i<<1|1][j<<1|1] < R){                add_edge(i<<1|1, j<<1);                add_edge(j<<1|1, i<<1);            }            if(d[i<<1][j<<1|1] < R){                add_edge(i<<1, j<<1);                add_edge(j<<1|1, i<<1|1);            }        }    }    //进行判断    return two_sat();}int main(){//    freopen("test.in", "r", stdin);    while(scanf("%d", &n)!=EOF){        for(int i = 0; i < n; i ++){            scanf("%d%d%d%d", &point[i<<1].x, &point[i<<1].y, &point[i<<1|1].x, &point[i<<1|1].y);        }        predour();        int l = 0 , r = 800000001;        while(l < r){            int m = (l + r)>>1;            if(test(m))                l = m+1;            else                r = m;        }        printf("%.2f\n", sqrt(l-1.0)*0.5);    }    return 0;}


原创粉丝点击