Poj2296

题意:给定n个点,然后在每个点在一个正方形的上边或者下边的中点,并且所有的正方形等大且不能重叠。求正方形最大的边长是多少。

思路:很明显的二分边长+判定。不过判定要用到2-sat,算是2-sat的入门题吧。

       所谓的2-sat,就是对于若干个bool不等式,然后对于会互相干扰(即不能同时成立的),连边处理,然后对于每一块枚举一个点的值,判断是否可行。出现冲突即无解。具体看代码吧。

下面2-sat部分是LRJ的模板,写的挺清晰的。。

  1 /*
  2  * Author:  Yzcstc
  3  * Created Time:  2014/3/8 13:40:50
  4  * File Name: Poj2296.cpp
  5  */
  6 #include<cstdio>
  7 #include<iostream>
  8 #include<cstring>
  9 #include<cstdlib>
 10 #include<cmath>
 11 #include<algorithm>
 12 #include<string>
 13 #include<map>
 14 #include<set>
 15 #include<vector>
 16 #include<queue>
 17 #include<stack>
 18 #include<ctime>
 19 #define M0(x) memset(x, 0, sizeof(x))
 20 #define rep(i, a, b) for (int i = (a); i <= (b); ++i)
 21 #define red(i, a, b) for (int i = (a); i >= (b); --i)
 22 #define PB push_back
 23 #define Inf 0x3fffffff
 24 #define eps 1e-8
 25 #define maxn 500
 26 typedef long long LL;
 27 using namespace std;
 28 struct TwoSat{
 29      int n;
 30      vector<int> G[maxn * 2];
 31      bool mark[maxn * 2];
 32      int S[maxn * 2], c;
 33      bool dfs(int x){ // 搜索一组解 
 34           if (mark[x^1]) return false; //出现冲突 
 35           if (mark[x]) return true;
 36           mark[x] = true;
 37           S[c++] = x;
 38           for (int i = 0; i < G[x].size(); ++i)
 39               if (!dfs(G[x][i])) return false;
 40           return true;
 41      }
 42 
 43      void init(int n){
 44           this->n = n;
 45           for (int i = 0; i < 2 * n; ++i)
 46               G[i].clear();
 47           memset(mark, 0, sizeof(mark));
 48      }
 49 
 50      void add_clause(int x, int xv, int y, int yv){
 51            x = x * 2 + xv;
 52            y = y * 2 + yv; //x,y不能同时存在,那么如果选了y,合法解必定要选x^1
 53            G[x^1].push_back(y);  
 54            G[y^1].push_back(x);
 55      }
 56 
 57      bool solve(){
 58            for (int i = 0; i < n * 2; i += 2)
 59                if (!mark[i] && !mark[i+1]){
 60                     c = 0;
 61                     if (!dfs(i)){ //枚举2种取值都无解 
 62                           while (c > 0) mark[S[--c]] = false;
 63                           if (!dfs(i+1)) return false;
 64                     }
 65                }
 66            return true;
 67      }
 68 } Sat;
 69 
 70 int n, X[200], Y[200], T;
 71 
 72 void init(){
 73     scanf("%d", &n);
 74     for (int i = 0; i < n; ++i)
 75         scanf("%d%d", &X[i], &Y[i]);
 76 }
 77 
 78 bool check(int r){
 79      Sat.init(n);
 80      for (int i = 0; i < n; ++i)
 81          for (int j = i + 1; j < n; ++j) if (i != j){ //分类讨论冲突情况 
 82               if (Y[i] < Y[j]){
 83                     if (Y[j] - Y[i] < r && abs(X[i] - X[j]) < r) Sat.add_clause(i, 0 , j, 0);
 84                     if (Y[j] - Y[i] < 2 * r && abs(X[i] - X[j]) < r) Sat.add_clause(i, 1 , j, 0);
 85                     if (Y[j] - Y[i] < r && abs(X[i] - X[j]) < r) Sat.add_clause(i, 1 , j, 1);
 86               }
 87                if (Y[i] > Y[j]){
 88                     if (Y[i] - Y[j] < r && abs(X[i] - X[j]) < r) Sat.add_clause(i, 0 , j, 0);
 89                     if (Y[i] - Y[j] < 2 * r && abs(X[i] - X[j]) < r) Sat.add_clause(i, 0 , j, 1);
 90                     if (Y[i] - Y[j] < r && abs(X[i] - X[j]) < r) Sat.add_clause(i, 1 , j, 1);
 91               }
 92               if (Y[i] == Y[j]){
 93                     if (abs(X[i] - X[j]) < r) Sat.add_clause(i, 0 , j, 0);
 94                     if (abs(X[i] - X[j]) < r) Sat.add_clause(i, 1 , j, 1);
 95               }
 96          }
 97      return Sat.solve();
 98 }
 99 
100 void solve(){
101     int l = 0, r = 40000, mid;
102     int cnt = 0, ans = 0;
103     while (l <= r){ //二分答案 
104         mid = (l + r) >> 1;
105         if (check(mid)) { ans = mid, l = mid + 1;}
106         else r = mid - 1;
107     }
108     printf("%d\n",ans);
109 }
110 
111 int main(){
112     freopen("a.in", "r", stdin);
113     freopen("a.out", "w", stdout);
114     scanf("%d", &T);
115     while (T--){
116          init();
117          solve();
118     }
119     fclose(stdin);  fclose(stdout);
120     return 0;
121 }

 

 
posted on 2014-03-08 16:14  yzcstc  阅读(357)  评论(0编辑  收藏  举报