• HDU3622(二分+2-SAT)


    Bomb Game

    Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 5647    Accepted Submission(s): 2036


    Problem Description

    Robbie is playing an interesting computer game. The game field is an unbounded 2-dimensional region. There are N rounds in the game. At each round, the computer will give Robbie two places, and Robbie should choose one of them to put a bomb. The explosion area of the bomb is a circle whose center is just the chosen place. Robbie can control the power of the bomb, that is, he can control the radius of each circle. A strange requirement is that there should be no common area for any two circles. The final score is the minimum radius of all the N circles.
    Robbie has cracked the game, and he has known all the candidate places of each round before the game starts. Now he wants to know the maximum score he can get with the optimal strategy.
     

    Input

    The first line of each test case is an integer N (2 <= N <= 100), indicating the number of rounds. Then N lines follow. The i-th line contains four integers x1i, y1i, x2i, y2i, indicating that the coordinates of the two candidate places of the i-th round are (x1i, y1i) and (x2i, y2i). All the coordinates are in the range [-10000, 10000].
     

    Output

    Output one float number for each test case, indicating the best possible score. The result should be rounded to two decimal places.
     

    Sample Input

    2 1 1 1 -1 -1 -1 -1 1 2 1 1 -1 -1 1 -1 -1 1
     

    Sample Output

    1.41 1.00
     

    Source

     
    题意:每次给出两个点,选其中一点为圆心画圆,半径任意。n次以后,画了n个圆,要求任意两个圆不能相交,问最小圆的半径最大为多少。
    思路:二分最小圆的半径。
         check方法:若a点和b点的距离小于2×半径,NOT a和b连边,NOT b和a连边。
             建图完毕后,强连通分量分解,2-SAT判断是否可行。
      1 //2017-08-27
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <algorithm>
      6 #include <vector>
      7 #include <iomanip>
      8 #include <cmath>
      9 
     10 using namespace std;
     11 
     12 const int N = 5010;
     13 const int M = N*N;
     14 const double EPS = 1e-6;
     15 int head[N], rhead[N], tot, rtot;
     16 struct Edge{
     17     int to, next;
     18 }edge[M], redge[M];
     19 
     20 void init(){
     21     tot = 0;
     22     rtot = 0;
     23     memset(head, -1, sizeof(head));
     24     memset(rhead, -1, sizeof(rhead));
     25 }
     26 
     27 void add_edge(int u, int v){
     28     edge[tot].to = v;
     29     edge[tot].next = head[u];
     30     head[u] = tot++;
     31 
     32     redge[rtot].to = u;
     33     redge[rtot].next = rhead[v];
     34     rhead[v] = rtot++;
     35 }
     36 
     37 vector<int> vs;//后序遍历顺序的顶点列表
     38 bool vis[N];
     39 int cmp[N];//所属强连通分量的拓扑序
     40 
     41 //input: u 顶点
     42 //output: vs 后序遍历顺序的顶点列表
     43 void dfs(int u){
     44     vis[u] = true;
     45     for(int i = head[u]; i != -1; i = edge[i].next){
     46         int v = edge[i].to;
     47         if(!vis[v])
     48           dfs(v);
     49     }
     50     vs.push_back(u);
     51 }
     52 
     53 //input: u 顶点编号; k 拓扑序号
     54 //output: cmp[] 强连通分量拓扑序
     55 void rdfs(int u, int k){
     56     vis[u] = true;
     57     cmp[u] = k;
     58     for(int i = rhead[u]; i != -1; i = redge[i].next){
     59         int v = redge[i].to;
     60         if(!vis[v])
     61           rdfs(v, k);
     62     }
     63 }
     64 
     65 //Strongly Connected Component 强连通分量
     66 //input: n 顶点个数
     67 //output: k 强连通分量数;
     68 int scc(int n){
     69     memset(vis, 0, sizeof(vis));
     70     vs.clear();
     71     for(int u = 0; u < n; u++)
     72       if(!vis[u])
     73         dfs(u);
     74     int k = 0;
     75     memset(vis, 0, sizeof(vis));
     76     for(int i = vs.size()-1; i >= 0; i--)
     77       if(!vis[vs[i]])
     78         rdfs(vs[i], k++);
     79     return k;
     80 }
     81 
     82 int n;
     83 struct Point{
     84     int x, y;
     85 }point[N];
     86 
     87 //input: 两个点
     88 //output: 两点间距离
     89 double distance(Point a, Point b){
     90     return sqrt((double)(a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
     91 }
     92 
     93 //input:radius 半径
     94 //output:true 通过选取某些点可以得到radius的分数,false 无法得到radius的分数
     95 bool check(double radius){
     96     init();
     97     for(int i = 0; i < 2*n; i++){
     98         for(int j = i+1; j < 2*n; j++){
     99             if((i^1) == j)continue;
    100             if(distance(point[i], point[j]) < 2*radius){//i与j存在矛盾
    101                 add_edge(i^1, j);// NOT i -> j
    102                 add_edge(j^1, i);// NOT j -> i
    103             }
    104         }
    105     }
    106     scc(2*n);
    107     for(int i = 0; i < 2*n; i += 2){
    108         if(cmp[i] == cmp[i^1])
    109               return false;
    110     }
    111     return true;
    112 }
    113 
    114 int main()
    115 {
    116     std::ios::sync_with_stdio(false);
    117     //freopen("inputC.txt", "r", stdin);
    118     while(cin>>n){
    119         for(int i = 0; i < n; i++){
    120             cin>>point[2*i].x>>point[2*i].y>>point[2*i+1].x>>point[2*i+1].y;
    121         }
    122         double l = 0.0, r = 40000.0, mid, ans = 0;
    123         while(r-l > EPS){
    124             mid = (l+r)/2;
    125             if(check(mid)){
    126                 ans = mid;
    127                 l = mid;
    128             }else
    129                   r = mid;
    130         }
    131         cout.setf(ios::fixed);
    132         cout<<setprecision(2)<<ans<<endl;
    133     }
    134 
    135     return 0;
    136 }
  • 相关阅读:
    jq遍历表单元素
    js变量陷阱
    Ueditor 添加插件
    this 和 self
    链接按钮重复单击
    关系运算符 与 函数
    flask 第七章 简陋版智能玩具 +MongoDB初识和基本操作
    flask 第六章 人工智能 百度语音合成 识别 NLP自然语言处理+simnet短文本相似度 图灵机器人
    flask 第五章 WebSocket GeventWebsocket 单聊群聊 握手 解密 加密
    flask 第四章 偏函数 Local空间转时间 myLocalStack RunFlask+request 请求上下文
  • 原文地址:https://www.cnblogs.com/Penn000/p/7440437.html
Copyright © 2020-2023  润新知