zoukankan      html  css  js  c++  java
  • 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
    ",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 }
     
  • 相关阅读:
    Postgresql HStore 插件试用小结
    postgres-xl 安装与部署 【异常处理】ERROR: could not open file (null)/STDIN_***_0 for write, No such file or directory
    GPDB 5.x PSQL Quick Reference
    postgresql 数据库schema 复制
    hive 打印日志
    gp与 pg 查询进程
    jquery table 发送两次请求 解惑
    python 字符串拼接效率打脸帖
    postgresql 日期类型处理实践
    IBM Rational Rose软件下载以及全破解方法
  • 原文地址:https://www.cnblogs.com/yzcstc/p/3588099.html
Copyright © 2011-2022 走看看