hdu3622:Bomb Game

给n<=100对点,从每对点里面挑一个并以这些挑出的点为圆心画圆,并且这些圆不能互相覆盖,找出一种方案使得这些圆半径中最小的那个最大。

“最小值最大”就是二分答案啦!考虑现在每个点都画出半径x的圆,如何选点呢?

可以发现选了一个点P之后与其距离相差2x内的点Q都不能被选,也就是“与P在同一对的另一个点P'    或    与Q在同一对的另一个点Q'”

有了或语句描述选点冲突,接下来就是2-SAT构图啦!

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<cmath>
  6 //#include<iostream>
  7 using namespace std;
  8 
  9 int n;
 10 #define maxn 111*2
 11 struct Edge{int to,next;};
 12 #define maxe maxn*maxn
 13 struct Graph
 14 {
 15     Edge edge[maxe];int le;
 16     int first[maxn],vis[maxn];
 17     void clear()
 18     {
 19         le=2;
 20         memset(first,0,sizeof(first));
 21     }
 22     void insert(int x,int y)
 23     {
 24         edge[le].to=y;
 25         edge[le].next=first[x];
 26         first[x]=le++;
 27     }
 28     void add_clause(int x,int y)
 29     {
 30         insert(x^1,y);
 31         insert(y^1,x);
 32     }
 33     int sta[maxn],top;
 34     bool dfs(int x)
 35     {
 36         if (vis[x^1]) return 0;
 37         if (vis[x]) return 1;
 38         vis[x]=1;
 39         sta[++top]=x;
 40         for (int i=first[x];i;i=edge[i].next)
 41             if (!dfs(edge[i].to)) return 0;
 42         return 1;
 43     }
 44     bool twosat()
 45     {
 46         memset(vis,0,sizeof(vis));
 47         for (int i=1;i<=n;i++)
 48             if (!vis[i*2] && !vis[i*2+1])
 49             {
 50                 top=0;
 51                 if (!dfs(i*2))
 52                 {
 53                     for (;top;top--) vis[sta[top]]=0;
 54                     if (!dfs(i*2+1)) return 0;
 55                 }
 56             }
 57         return 1;
 58     }
 59 }G;
 60 struct Point
 61 {
 62     int x,y;
 63 }a[maxn];
 64 double dis[maxn][maxn];
 65 #define eps 1e-5
 66 double sqr(double x) {return x*x;}
 67 double caldis(int p,int q)
 68 {
 69     return sqrt(sqr(a[p].x-a[q].x)+sqr(a[p].y-a[q].y));
 70 }
 71 bool judge(double x)
 72 {
 73     for (int i=1;i<=n;i++)
 74         for (int j=i+1;j<=n;j++)
 75         {
 76             if (dis[i*2][j*2]<x*2) G.add_clause(i*2+1,j*2+1);
 77             if (dis[i*2+1][j*2]<x*2) G.add_clause(i*2,j*2+1);
 78             if (dis[i*2][j*2+1]<x*2) G.add_clause(i*2+1,j*2);
 79             if (dis[i*2+1][j*2+1]<x*2) G.add_clause(i*2,j*2);
 80         }
 81     return G.twosat();
 82 }
 83 int main()
 84 {
 85     while (~scanf("%d",&n))
 86     {
 87         for (int i=1;i<=n;i++)
 88             scanf("%d%d%d%d",&a[i*2].x,&a[i*2].y,&a[i*2+1].x,&a[i*2+1].y);
 89         double L=0.0,R=0.0;
 90         for (int i=2;i<=n*2+1;i++)
 91             for (int j=2;j<=n*2+1;j++)
 92                 dis[i][j]=caldis(i,j),R=max(R,dis[i][j]);
 93         while (R-L>=eps)
 94         {
 95             G.clear();
 96             double mid=(L+R+eps)/2;
 97             if (judge(mid)) L=mid;
 98             else R=mid-eps;
 99         }
100         printf("%.2lf\n",L);
101     }
102     return 0;
103 }
View Code

 

posted @ 2017-07-20 10:42  Blue233333  阅读(197)  评论(0编辑  收藏  举报