zoukankan      html  css  js  c++  java
  • HDU3622二分+2-sat

      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
    ",L);
    108     }
    109     return 0;
    110 }
  • 相关阅读:
    【BZOJ3533】向量集(SDOI2014)-线段树+凸壳+二分
    【BZOJ4869】相逢是问候(六省联考2017)-扩展欧拉定理+线段树
    【BZOJ4012】开店(HNOI2015)-动态点分治+set
    【BZOJ1095】捉迷藏(ZJOI2007)-动态点分治+堆
    【BZOJ2299】向量(HAOI2011)-裴蜀定理
    【BZOJ4942】整数(NOI2017)-线段树+压位
    【BZOJ3594】方伯伯的玉米田(SCOI2014)-DP+二维树状数组
    背包DP专题
    【2018.11.7】【luoguNOIp 热身赛】解题报告及总结
    【一天一DP计划】状压DP
  • 原文地址:https://www.cnblogs.com/little-w/p/3585602.html
Copyright © 2011-2022 走看看