题目大意:

给定n个点,给每个点都安排一个相同的正方形,使这个点落在正方形的下底边的中间或者上底边的中间,并让这n个正方形不出现相互覆盖,可以共享同一条边,求

这个正方形最大的边长

 

这里明显看出n个点,每个点都只有在上底边和下底边两种选择,所以这里是2-sat解决

这里全都是整数,而因为点在正方形的中间,所以/2后会有小数

我这里初始将所有点都扩大两倍,那么答案必然扩大两倍,所以我们二分只考虑边长为偶数的情况即可,这样计算结果就不会出现小数了

最后将答案除以2便是

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <vector>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 #define N 210
  8 int n , S[N] , x[N] , y[N] , k;
  9 vector<int> G[N];
 10 bool mark[N];
 11 
 12 struct Rec{
 13     int x[4] , y[4];
 14     bool in(Rec a){
 15         if(a.x[0]>=x[1] || a.y[0]>=y[2] || a.x[1]<=x[0] || a.y[2]<=y[0]) return false;
 16         return true;
 17     }
 18 }a , b , c , d;
 19 
 20 void init(int n)
 21 {
 22     memset(mark , 0 , sizeof(mark));
 23     for(int i=0 ; i<2*n ; i++) G[i].clear();
 24 }
 25 
 26 bool dfs(int u)
 27 {
 28     if(mark[u]) return true;
 29     if(mark[u^1]) return false;
 30     mark[u] = true;
 31     S[k++] = u;
 32     for(int i=0 ; i<G[u].size() ; i++)
 33         if(!dfs(G[u][i])) return false;
 34     return true;
 35 }
 36 
 37 bool solve(int n)
 38 {
 39     for(int i=0 ; i<2*n ; i+=2)
 40         if(!mark[i] && !mark[i^1]){
 41             k= 0;
 42             if(!dfs(i)){
 43                 while(k) mark[S[--k]] = false;
 44                 if(!dfs(i^1)) return false;
 45             }
 46         }
 47     return true;
 48 }
 49 
 50 void add_clause(int a , int p , int b , int q)
 51 {
 52     int m=2*a+p;
 53     int n=2*b+q;
 54     //m,n互斥
 55     G[m].push_back(n^1);
 56     G[n].push_back(m^1);
 57 }
 58 
 59 bool check(int m)
 60 {
 61     init(n);
 62     if(m&1) m--;
 63     for(int i=0 ; i<n ; i++){
 64         for(int j=i+1 ; j<n ; j++){
 65             //down , up 2*2 four case
 66             a.x[0] = x[i]-m/2 , a.y[0] = y[i];
 67             a.x[1] = x[i]+m/2 , a.y[1] = y[i];
 68             a.x[2] = a.x[1]   , a.y[2] = y[i]+m;
 69             a.x[3] = a.x[0]   , a.y[3] = y[i]+m;
 70 
 71             b.x[0] = x[j]-m/2 , b.y[0] = y[j];
 72             b.x[1] = x[j]+m/2 , b.y[1] = y[j];
 73             b.x[2] = b.x[1]   , b.y[2] = y[j]+m;
 74             b.x[3] = b.x[0]   , b.y[3] = y[j]+m;
 75 
 76             c.x[0] = x[i]-m/2 , c.y[0] = y[i]-m;
 77             c.x[1] = x[i]+m/2 , c.y[1] = y[i]-m;
 78             c.x[2] = c.x[1]   , c.y[2] = y[i];
 79             c.x[3] = c.x[0]   , c.y[3] = y[i];
 80 
 81             d.x[0] = x[j]-m/2 , d.y[0] = y[j]-m;
 82             d.x[1] = x[j]+m/2 , d.y[1] = y[j]-m;
 83             d.x[2] = d.x[1]   , d.y[2] = y[j];
 84             d.x[3] = d.x[0]   , d.y[3] = y[j];
 85 
 86             if(a.in(b)) add_clause(i , 0 , j , 0);
 87             if(a.in(d)) add_clause(i , 0 , j , 1);
 88             if(c.in(b)) add_clause(i , 1 , j , 0);
 89             if(c.in(d)) add_clause(i , 1 , j , 1);
 90         }
 91     }
 92     return solve(n);
 93 }
 94 
 95 int main()
 96 {
 97   //  freopen("in.txt" , "r" , stdin);
 98     int T;
 99     scanf("%d" , &T);
100     while(T--)
101     {
102         scanf("%d" , &n);
103         for(int i=0 ; i<n ; i++){
104             scanf("%d%d" , &x[i] , &y[i]);
105             x[i]*=2 , y[i]*=2;
106         }
107         int l=0 , r=1e5 , ret=l;
108         while(l<=r){
109             int m = (l+r)>>1;
110             if(check(m)) ret=m , l=m+1;
111             else r=m-1;
112         }
113         printf("%d\n" , ret/2);
114     }
115     return 0;
116 }

 

 posted on 2015-07-28 09:18  Love风吟  阅读(153)  评论(0编辑  收藏  举报