【2-SAT】HDU3622-Bomb Game

【题目大意】

给n对炸弹可以放置的位置(每个位置为一个二维平面上的点),每次放置炸弹是时只能选择这一对中的其中一个点,每个炸弹爆炸的范围半径都一样,控制爆炸的半径使得所有的爆炸范围都不相交(可以相切),求解这个最大半径。

【思路】

显然是二分答案!二分半径,2-SAT建图部分是最裸的。

【错误点】

注意一下精度啊,HDU根本不提供所谓的±0.01..

一开始写了printf("%.2f ",floor(ub*100)/100);

事实上写printf("%.2f ",ub);就好啦。

  1 #include<bits/stdc++.h>
  2 #define eps 1e-8
  3 using namespace std;
  4 const int MAXN=250;
  5 const int INF=0x7fffffff;
  6 int n;
  7 int x[MAXN],y[MAXN];
  8 int dfn[MAXN],low[MAXN],col[MAXN],instack[MAXN],colcnt,cnt;
  9 vector<int> E[MAXN];
 10 stack<int> S; 
 11 
 12 void addedge(int u,int v)
 13 {
 14     E[u].push_back(v);
 15 }
 16 
 17 double dist(int x1,int y1,int x2,int y2)
 18 {
 19     double ret=sqrt((double)(x1-x2)*(x1-x2)+(double)(y1-y2)*(y1-y2));
 20     //cout<<x1<<' '<<x2<<' '<<y1<<' '<<y2<<' '<<ret<<endl;
 21     return ret;
 22 }
 23 
 24 void tarjan(int u)
 25 {
 26     dfn[u]=low[u]=++cnt;
 27     instack[u]=1;
 28     S.push(u);
 29     for (int i=0;i<E[u].size();i++)
 30     {
 31         int v=E[u][i];
 32         if (!instack[v])
 33         {
 34             tarjan(v);
 35             low[u]=min(low[u],low[v]);
 36                 
 37         }
 38         else if (instack[v]==1) low[u]=min(low[u],dfn[v]);
 39     }
 40     
 41     if (dfn[u]==low[u])
 42     {
 43         colcnt++;
 44         int x;
 45         do
 46         {
 47             x=S.top();
 48             col[x]=colcnt;
 49             instack[x]=2;
 50             S.pop();
 51         }while (x!=u);
 52     }
 53 }
 54 
 55 void build(double r)
 56 {
 57     for (int i=0;i<MAXN;i++) vector<int>().swap(E[i]);
 58     for (int i=1;i<=n-1;i++)
 59         for (int j=i+1;j<=n;j++)
 60         {
 61             if (dist(x[i],y[i],x[j],y[j])<2*r) addedge(i,j+n),addedge(j,i+n);
 62             if (dist(x[i],y[i],x[j+n],y[j+n])<2*r) addedge(i,j),addedge(j+n,i+n);
 63             if (dist(x[i+n],y[i+n],x[j],y[j])<2*r) addedge(i+n,j+n),addedge(j,i);
 64             if (dist(x[i+n],y[i+n],x[j+n],y[j+n])<2*r) addedge(i+n,j),addedge(j+n,i); 
 65         }
 66 }
 67 
 68 void init()
 69 {
 70     for (int i=1;i<=n;i++)
 71     {
 72         scanf("%d%d",&x[i],&y[i]);
 73         scanf("%d%d",&x[i+n],&y[i+n]);
 74     }
 75 }
 76 
 77 void solve()
 78 {
 79     double lb=0,ub=INF;
 80     while (ub-lb>eps)
 81     {
 82         double mid=(lb+ub)/2;
 83         build(mid);
 84         memset(instack,0,sizeof(instack));
 85         colcnt=cnt=0;
 86         for (int i=1;i<=2*n;i++) if (!instack[i]) tarjan(i);
 87         int flag=1;
 88         for (int i=1;i<=n;i++)
 89             if (col[i]==col[i+n])
 90             {
 91                 flag=0;
 92                 break;
 93             }
 94         if (flag) lb=mid;
 95             else ub=mid;
 96     }
 97     printf("%.2f
",ub);
 98 }
 99 
100 int main()
101 {
102     while (scanf("%d",&n)!=EOF)
103     {
104         init();
105         solve();
106     }
107     return 0;
108 }

[写随机数据上瘾了所以这次也附上]

 1 #include<bits/stdc++.h>
 2 
 3 int main()
 4 {
 5     freopen("test.out","w",stdout);
 6     for (int i=1;i<=20;i++)
 7     {
 8         int n=rand()%98+2;
 9         printf("%d
",n);
10         for (int j=1;j<=n;j++)
11         {
12             int x=rand()%2001-1000,y=rand()%2001-1000;
13             printf("%d %d ",x,y);
14             x=rand()%2001-1000,y=rand()%2001-1000;
15             printf("%d %d
",x,y);
16         }
17     }
18     return 0;
19 }
原文地址:https://www.cnblogs.com/iiyiyi/p/5929862.html