[2-sat]HDOJ3622 Bomb Game

题意:给n对炸弹,每对炸弹选其中一个爆炸。

每个炸弹爆炸的半径相同 圆不能相交, 求最大半径

 

2-sat简介

二分半径, 枚举n*2个炸弹

若i炸弹与j炸弹的距离小于半径*2 则建边

比如  第一对炸弹的第一个 与 第二对炸弹的第一个 距离小于半径*2

    则 建立 第一对炸弹的第一个$\Rightarrow $第二对炸弹的第二个 、第二对炸弹的第一个$\Rightarrow $第一对炸弹的第二个

然后 通过判断能否取到n个炸弹 来判断 能否取该半径

 

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4 typedef pair<double, double> PI;
  5 const double eps=1e-6;
  6 #define INF 0x3f3f3f3f
  7 
  8 const int N=105*2;
  9 const int M=N*N;
 10 //注意n是拆点后的大小 即 n <<= 1 N为点数(注意要翻倍) M为边数 i&1=0为i真 i&1=1为i假
 11 struct Edge
 12 {
 13     int to, nex;
 14 }edge[M];
 15 //注意 N M 要修改
 16 int head[N], edgenum;
 17 void addedge(int u, int v)
 18 {
 19     Edge E={v, head[u]};
 20     edge[edgenum]=E;
 21     head[u]=edgenum++;
 22 }
 23 
 24 bool mark[N];
 25 int Stack[N], top;
 26 void init()
 27 {
 28     memset(head, -1, sizeof(head));
 29     edgenum=0;
 30     memset(mark, 0, sizeof(mark));
 31 }
 32 
 33 bool dfs(int x)
 34 {
 35     if(mark[x^1])
 36         return false;//一定是拆点的点先判断
 37     if(mark[x])
 38         return true;
 39     mark[x]=true;
 40     Stack[top++]=x;
 41     for(int i=head[x];i!=-1;i=edge[i].nex)
 42         if(!dfs(edge[i].to))
 43             return false;
 44     return true;
 45 }
 46 
 47 bool solve(int n)
 48 {
 49     for(int i=0;i<n;i+=2)
 50         if(!mark[i] && !mark[i^1])
 51         {
 52             top=0;
 53             if(!dfs(i))
 54             {
 55                 while(top)
 56                     mark[Stack[--top]]=false;
 57                 if(!dfs(i^1))
 58                     return false;
 59             }
 60         }
 61     return true;
 62 }
 63 
 64 PI a[205];
 65 double dis(PI a, PI b)
 66 {
 67     return sqrt((a.first-b.first)*(a.first-b.first)+(a.second-b.second)*(a.second-b.second));
 68 }
 69 
 70 int main()
 71 {
 72     int n;
 73     while(~scanf("%d", &n))
 74     {
 75         for(int i=0;i<n;i++)
 76         {
 77             double x1, y1, x2, y2;
 78             scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
 79             a[i*2]=make_pair(x1, y1);
 80             a[i*2+1]=make_pair(x2, y2);
 81         }
 82         double l=0, r=15000;
 83         while(r-l>=eps)
 84         {
 85             double m=(l+r)/2.0;
 86             init();
 87             for(int i=0;i<n*2;i++)
 88                 for(int j=i+1+!(i&1);j<2*n;j++)
 89                     if(dis(a[i], a[j])<2*m)
 90                     {
 91                         addedge(i, j^1);
 92                         addedge(j, i^1);
 93                     }
 94             if(solve(n*2))
 95                 l=m;
 96             else
 97                 r=m;
 98         }
 99         printf("%.2f\n", r);
100     }
101     return 0;
102 }
HDOJ 3622

 

posted @ 2015-08-18 10:43  Empress  阅读(266)  评论(0编辑  收藏  举报