HDU 3622 —— Bomb Game(2-SAT,二分答案)

来源:互联网 发布:淘宝网注册会员数量 编辑:程序博客网 时间:2024/05/17 08:45

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

题意:有N对点,每对点中必须选择一个点,以每个选择点为中心画圆,每个圆的半径不作要求,但唯一限制的是所有圆不能相交,问画出来的所有圆中半径最小的值,最大是多少?

感觉跟《训练指南》中2-SAT这块的例题很类似。

对答案进行二分,把问题转化为特定半径的可行性判断。假设当前最小半径是mid,那么如果两个点(不是同一对的)的距离小于2*mid,那么说明两圆相交,有冲突,那么就连边到它们各自取反的点。然后就是很常规的2-SAT问题了。

PS:写的时候智商又捉急了。。。每次判断两个点是否冲突都去计算一次距离,TLE了很多下,纠结了很久才发现是这个地方大量的重复计算,而且还是很蛋疼地浮点数平方和开方,后来开了个数组记录这些结果,马上变成400+MS了,看来浮点数的威力还是不容小视。。。

#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<stack>#include<algorithm>using namespace std;#define pb push_back#define N 200vector<int>  V[N];const double eps = 1e-5;double x[N], y[N], d[N][N];int n;double dist(int a, int b){    return sqrt(pow(x[a]-x[b],2.0) + pow(y[a]-y[b],2.0));}bool mark[N];int S[N], c;bool dfs(int x){    if(mark[x^1])   return 0;    if(mark[x]) return 1;    mark[x]=1;    S[c++]=x;    for(int i=0; i<V[x].size(); i++){        if(!dfs(V[x][i]))   return 0;    }    return 1;}bool check(){    memset(mark,0,sizeof(mark));    for(int i=0; i<n*2; i+=2){        if(!mark[i] && !mark[i+1]){            c = 0;            if(!dfs(i)){                while(c>0)  mark[S[--c]]=0;                if(!dfs(i+1))   return 0;            }        }    }    return 1;}void solve(){    double low=0.0, top=40000.0, mid;    while(top-low>eps){        mid = low+top;        for(int i=0; i<n*2; i++)    V[i].clear();        for(int i=0; i<n*2; i++){            for(int j=i+1; j<n*2; j++){                if((i>>1)==(j>>1))  continue;                double tmp = d[i][j];                if(tmp<mid){                    V[i^1].pb(j);                    V[j^1].pb(i);                }            }        }        mid*=0.5;        if(check())  low=mid;        else    top=mid;    }    printf("%.2lf\n", low);}int main(){    while(~scanf("%d", &n)){        for(int i=0; i<n; i++){            scanf("%lf %lf %lf %lf", x+i*2, y+i*2, x+i*2+1, y+i*2+1);        }        for(int i=0; i<n*2; i++){            for(int j=i+1; j<n*2; j++){                d[i][j] = d[j][i] = dist(i,j);            }            d[i][i]=0.0;        }        solve();    }    return 0;}


0 0
原创粉丝点击