题目大意:
给定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 " , ret/2); 114 } 115 return 0; 116 }