1 /*HDU3622
2 这道题是2-sat问题的体型之一,二分答案,2-sat判断是否有自适应的解,从而找到最大的最小值或最小的最大值
3 这道题有一定的思维上的难度。
4 二分半径,若不同组的两个点i和j间的距离小于2*rad,则i和j是矛盾点,连上相应的边,求2-sat即可。
5
6 这道题有两种建模的方式:
7 1、同一组的为一个对象(正好每个对象满足二选一的特点)
8 2、每个点为一个对象(这种情况下,原来属于同组的两个点就是矛盾点了)
9 */#include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <math.h>
13 #include <ctype.h>
14 #include <string>
15 #include <iostream>
16 #include <sstream>
17 #include <vector>
18 #include <queue>
19 #include <stack>
20 #include <map>
21 #include <list>
22 #include <set>
23 #include <algorithm>
24 #define INF 0x3f3f3f3f
25 #define LL long long
26 #define eps 1e-4
27 #define maxn 210
28 using namespace std;
29 double X[2*maxn];
30 double Y[2*maxn];
31 struct TwoSAT
32 {
33 int n;
34 vector<int> G[maxn*2];
35 bool mark[maxn*2];
36 int S[maxn*2],c;
37 bool dfs(int x)
38 {
39 if (mark[x^1]) return false;//真假同时被标记,逻辑矛盾
40 if (mark[x]) return true;//x被标记,意味着下面的节点也被标记,思想是记忆化搜索
41 mark[x]=true;
42 S[c++]=x;
43 for(int i=0; i<G[x].size(); i++)
44 if(!dfs(G[x][i])) return false; //同一个强联通分量应该表上同一种颜色
45 return true;
46 }
47 void init(int n)
48 {
49 this->n=n;
50 for(int i=0; i<n*2; i++) G[i].clear();
51 memset(mark,0,sizeof(mark));
52 }
53 void add_clause(int x,int y)//x,y不能同时存在
54 {
55 G[x].push_back(y^1);
56 // cout<<x<<"->"<<(y^1)<<endl;
57 G[y].push_back(x^1);
58 // cout<<y<<"->"<<(x^1)<<endl;
59 }
60 bool solve()
61 {
62 for(int i=0; i<n*2; i+=2)
63 {
64 if(!mark[i] && !mark[i^1])
65 {
66 c=0;//记得清零
67 if(!dfs(i))//将i标记为true
68 {
69 while(c>0) mark[S[--c]]=false;
70 if (!dfs(i^1)) return false;
71 }
72 }
73 }
74 return true;
75 }
76 } sat;
77 double dis(double x1,double y1,double x2,double y2)
78 {
79 return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
80 }
81 bool F(int n,double rad)
82 {
83 sat.init(n);
84 for(int i=1; i<2*n; i++)//枚举两两组之间
85 for(int j=0; j<i; j++)
86 {
87 if (i==(j^1)) continue;//Kの,j^1要加括号,深坑
88 if (2*rad-dis(X[j],Y[j],X[i],Y[i])>eps)
89 sat.add_clause(i,j);
90 }
91 return (sat.solve());
92 }
93 int n;
94 int main()
95 {
96 while(cin>>n)
97 {
98 for(int i=0; i<n; i++)
99 cin>>X[2*i]>>Y[2*i]>>X[2*i+1]>>Y[2*i+1];//注意建模时对应的点
100 double R=9999999,L=0;
101 while(R-L>eps)
102 {
103 double M=(R+L)/2;
104 if (F(n,M)) L=M;
105 else R=M;
106 }
107 printf("%.2lf\n",L);
108 }
109 return 0;
110 }