zoukankan      html  css  js  c++  java
  • hdu 2295 dlx重复覆盖+二分答案

     题目大意:

    有一堆雷达工作站,安放至多k个人在这些工作站中,找到一个最小的雷达监控半径可以使k个工作人所在的雷达工作站覆盖所有城市

    二分半径的答案,每次利用dlx的重复覆盖来判断这个答案是否正确

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <queue>
      6 #include <climits>
      7 #include <cmath>
      8 
      9 using namespace std;
     10 #define N 55
     11 #define MAXNODE 3000
     12 const double INF = 1e9;
     13 const double eps = 1e-8;
     14 
     15 int n,m,k;
     16 
     17 struct DLX{
     18     int n,m,size;
     19     int U[MAXNODE] , D[MAXNODE] , L[MAXNODE] , R[MAXNODE];
     20     int col[MAXNODE] , row[MAXNODE];
     21     int first[N] , cnt_col[N];
     22     bool v[MAXNODE];
     23 
     24     void init(int _n , int _m)
     25     {
     26         n = _n , m = _m , size = _m;
     27         for(int i=0 ; i<=m ; i++){
     28             U[i] = D[i] = i;
     29             L[i] = i-1 , R[i] = i+1;
     30             col[i] = i , row[i] = 0;
     31         }
     32         L[0] = m , R[m] = 0;
     33         for(int i=1 ; i<=n ; i++) first[i] = -1;
     34         for(int i=1 ; i<=m ; i++) cnt_col[i] = 0;
     35     }
     36 
     37     void link(int r , int c)
     38     {
     39         ++size;
     40         U[D[c]] = size , D[size] = D[c];
     41         U[size] = c , D[c] = size;
     42         cnt_col[c]++;
     43 
     44         if(first[r]<0) first[r] = L[size] = R[size] = size;
     45         else{
     46             R[size] = R[first[r]] , L[R[first[r]]] = size;
     47             L[size] = first[r] , R[first[r]] = size;
     48         }
     49         row[size] = r , col[size] = c;
     50     }
     51 
     52     void Remove(int c)
     53     {
     54         for(int i=D[c] ; i!=c ; i=D[i]){
     55             L[R[i]] = L[i] , R[L[i]] = R[i];
     56         }
     57     }
     58 
     59     void Resume(int c)
     60     {
     61         for(int i=U[c] ; i!=c ; i=U[i]){
     62             L[R[i]] = R[L[i]] = i;
     63         }
     64     }
     65 
     66     int f()
     67     {
     68         int ret = 0;
     69         for(int c=R[0] ; c!=0 ; c=R[c]) v[c]=true;
     70         for(int c=R[0] ; c!=0 ; c=R[c])
     71             if(v[c]){
     72                 ret++;
     73                 v[c] = false;
     74                 for(int i=D[c] ; i!=c ; i=D[i])
     75                     for(int j=R[i] ; j!= i ; j=R[j])
     76                         v[col[j]]=false;
     77             }
     78         return ret;
     79     }
     80 
     81     bool Dance(int d)
     82     {
     83         //这里k表示题目所给意思让我们至多在dlx中选择k行
     84         if(d+f() > k) return false;
     85         if(!R[0]) return d<=k;
     86         int st = R[0];
     87         for(int i=R[0] ; i!=0 ; i=R[i])
     88             if(cnt_col[st]>cnt_col[i]) st=i;
     89 
     90         for(int i=D[st] ; i!=st ; i=D[i]){
     91             Remove(i);
     92             for(int j=R[i] ; j!=i ; j=R[j]) Remove(j);
     93             if(Dance(d+1)) return true;
     94             for(int j=L[i] ; j!=i ; j=L[j]) Resume(j);
     95             Resume(i);
     96         }
     97         return false;
     98     }
     99 }dlx;
    100 
    101 struct Point{
    102     double x,y;
    103 }p1[N] , p2[N];
    104 
    105 double getDis(int i , int j)
    106 {
    107     return sqrt((p1[i].x-p2[j].x)*(p1[i].x-p2[j].x)+(p1[i].y-p2[j].y)*(p1[i].y-p2[j].y));
    108 }
    109 
    110 bool check(double mid)
    111 {
    112     dlx.init(m , n);
    113     for(int i=1 ; i<=m ; i++){
    114         for(int j=1; j<=n ;j++){
    115             if(getDis(j , i)<=mid) dlx.link(i,j);
    116         }
    117     }
    118     return dlx.Dance(0);
    119 }
    120 
    121 double bin_search()
    122 {
    123     double l=0 , r=INF;
    124     while(r-l>eps){
    125         double mid = (l+r)/2;
    126         if(check(mid)) r=mid;
    127         else l=mid;
    128     }
    129     return r;
    130 }
    131 
    132 int main()
    133 {
    134    // freopen("a.in" , "r" , stdin);
    135     int T;
    136     scanf("%d" , &T);
    137     while(T--)
    138     {
    139         scanf("%d%d%d" , &n , &m , &k);
    140         for(int i=1 ; i<=n ; i++)
    141             scanf("%lf%lf" , &p1[i].x , &p1[i].y);
    142         for(int i=1 ; i<=m ; i++)
    143             scanf("%lf%lf" , &p2[i].x , &p2[i].y);
    144         printf("%.6lf
    " , bin_search());
    145     }
    146     return 0;
    147 }
  • 相关阅读:
    使用hugo在gitee上写blog
    golang初识2
    golang初识1
    install go on ubuntu
    sql优化的几种方式
    UpdatePanel 无刷新弹出窗口
    .net web 点击链接在页面指定位置显示DIV的问题
    重建主键
    sql 日期时间格式转换
    UpdatePanel无法直接弹出窗口的解决
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4508882.html
Copyright © 2011-2022 走看看