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

    题意:
         给你N组炸弹,每组2个,让你在这N组里面选取N个放置,要求(1)每组只能也必须选取一个(2)炸弹与炸弹之间的半径相等(3)不能相互炸到对方。求最大的可放置半径。


    思路:

         二分去枚举半径,然后用2sat去判断是否可行,在2sat里,每组炸弹的两个是正常对,任何两组的任何两个距离小于等于mid那么这两个是矛盾对。这样强连通缩短,然后判断有没有一组是在同一个强连通块里的,没有那么就ok继续更新二分查找答案。

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<stack>
    
    #define N_node 200 + 10
    #define N_edge 100000 + 100
    
    using namespace std;
    
    typedef struct
    {
       int to ,next;
    }STAR;
    
    typedef struct
    {
       double x1 ,x2 ,y1 ,y2;
    }NODE;
    
    STAR E1[N_edge] ,E2[N_edge];
    NODE node[111];
    int list1[N_node] ,list2[N_node] ,tot;
    int Belong[N_node] ,cnt;
    int mark[N_node];
    stack<int>st;
    
    void add(int a , int b)
    {
       E1[++tot].to = b;
       E1[tot].next = list1[a];
       list1[a] = tot;
       
       E2[tot].to = a;
       E2[tot].next = list2[b];
       list2[b] = tot;
    }
    
    void DFS1(int s)
    {
       mark[s] = 1;
       for(int k = list1[s] ;k ;k = E1[k].next)
       {
          int xin = E1[k].to;
          if(!mark[xin]) DFS1(xin);
       }
       st.push(s);
    }
    
    void DFS2(int s)
    {
       mark[s] = 1;
       Belong[s] = cnt;
       for(int k = list2[s] ;k ;k = E2[k].next)
       {
          int xin = E2[k].to;
          if(!mark[xin]) DFS2(xin);
       }
    }
    
    double diss(double x1 ,double y1 ,double x2 ,double y2)
    {
       double tmp = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
       return sqrt(tmp);
    }
                                              
    
    bool ok(double mid ,int n)
    {
       memset(list1 ,0 ,sizeof(list1));
       memset(list2 ,0 ,sizeof(list2));
       tot = 1;
       for(int i = 0 ;i < n ;i ++)
       for(int j = i + 1 ;j < n ;j ++)
       {
          int a ,b;
          double dis = diss(node[i].x1 ,node[i].y1 ,node[j].x1 ,node[j].y1);
          if(dis <= mid)
          {
             a = i * 2 ,b = j * 2;
             add(a ,b^1) ,add(b ,a^1);
          }
          dis = diss(node[i].x1 ,node[i].y1 ,node[j].x2 ,node[j].y2);
          if(dis <= mid)
          {
             a = i * 2 ,b = j * 2 + 1;
             add(a ,b^1) ,add(b ,a^1);
          }
          dis = diss(node[i].x2 ,node[i].y2 ,node[j].x1 ,node[j].y1);
          if(dis <= mid)
          {
             a = i * 2 + 1,b = j * 2;
             add(a ,b^1) ,add(b ,a^1);
          }
          dis = diss(node[i].x2 ,node[i].y2 ,node[j].x2 ,node[j].y2);
          if(dis <= mid)
          {
             a = i * 2 + 1,b = j * 2 + 1;
             add(a ,b^1) ,add(b ,a^1);
          }
       }
       memset(mark ,0 ,sizeof(mark));
       while(!st.empty())st.pop();
       for(int i = 0 ;i < n * 2 ;i ++)
       if(!mark[i]) DFS1(i);
       memset(mark ,0 ,sizeof(mark));
       cnt = 0;
       while(!st.empty())
       {
          int xin = st.top();
          st.pop();
          if(mark[xin]) continue;
          ++cnt;
          DFS2(xin);
       }
       int mk = 0;
       for(int i = 0 ;i < n * 2 ;i += 2)
       {
          if(Belong[i]  == Belong[i^1])
          mk = 1;
       }
       return !mk;
    }
    
    int main ()
    {
        int n ,i;
        while(~scanf("%d" ,&n))
        {
           for(i = 0 ;i < n ;i ++)
           scanf("%lf %lf %lf %lf" ,&node[i].x1 ,&node[i].y1 ,&node[i].x2 ,&node[i].y2);
           double low ,mid ,up ,ans = 0;
           low = 0 ,up = 2000000000;
           for(i = 1 ;i <= 100 ;i ++)
           {
                mid = (low + up) / 2;
                if(ok(mid ,n))
                ans = low = mid;
                else up = mid;
           }
           printf("%.2lf
    " ,ans/2);
       }
       return 0;
    }
           
    

  • 相关阅读:
    团队计划
    python数据处理学习
    ShellExecute函数
    WinAPI WinMain函数
    I2C相关知识学习
    JavaScript多元运算符
    彻底理解js中的&&和||
    彻底理解线程同步与同步代码块synchronized
    JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释
    JS参数使用带参数的方法
  • 原文地址:https://www.cnblogs.com/csnd/p/12063017.html
Copyright © 2011-2022 走看看