DLX by java (example : hdu 2295)

有N个城市,M个雷达站,K个操作员,从M个雷达站中选择K个,来覆盖所有的N城市,每个雷达有相同的覆盖半径,问:最小的覆盖半径是多少

最小支配集问题,最小支配集属于NP难题,找不到多项式解法,所有只能搜索,但是普通的搜索是过不了的,鉴于这种类型的题,可以用一种的特殊的结构–双向链表,于是就可以用DLX来优化这个搜索.
可以先二分距离,然后用DLX判断就行了。

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.NavigableSet;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
import java.util.Set;
import java.util.SortedSet;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeSet;

import org.omg.CORBA.Object;




public class Main {

    public static void main(String[] args) throws IOException{
           StreamTokenizer cin = new StreamTokenizer(new BufferedInputStream(System.in)); 
           InputReader in = new InputReader(System.in)  ;
           PrintWriter out = new PrintWriter(System.out) ;

           int t = in.nextInt() ;
           for(int i = 1 ; i <= t ; i++){
                new Task().solve(in, out)  ;   //out.flush() ;
           }

           out.flush() ; 


    }


}

class  Task{
       static final double  eps = 1e-8 ;
       static final int N = 62 ; 
       static double[] dx = new double[N] ;
       static double[] dy = new double[N] ;
       static double[] px = new double[N] ;
       static double[] py = new double[N] ;
       static double[][] dist = new double[N][N] ;

       ArrayList<Double> radiu = new ArrayList<Double>() ;

       int  n , m ,  k ;

       public void solve(InputReader in , PrintWriter out) throws IOException{
              n = in.nextInt() ;
              m = in.nextInt() ;
              k = in.nextInt() ;
              for(int i = 1 ; i <= n ; i++){
                    dx[i] = in.nextDouble() ;
                    dy[i] = in.nextDouble() ;  
              }
              for(int i = 1 ; i <= m ; i++){
                    px[i] = in.nextDouble() ;
                    py[i] = in.nextDouble() ;  
              }

              for(int i = 1 ; i <= m ; i++){  
                   for(int j = 1 ; j <= n ; j++){
                        dist[i][j]  =  Math.pow(px[i] - dx[j] , 2.0) + Math.pow(py[i] - dy[j] , 2.0) ;
                        radiu.add(dist[i][j]) ;
                   }         
              }

              Collections.sort(radiu) ;

              out.printf("%.6f" , Math.sqrt(bs()));
              out.println();

       }

       boolean  ok(double d){  
                 DLX dlx = new DLX(m , n , k) ; 
                 for(int i = 1 ; i <= m ; i++){  
                      for(int j = 1 ; j <= n ; j++){  
                           if(dist[i][j] - eps < d){
                                  dlx.Link(i , j) ;  
                           }
                      }  
                 }  
                 return dlx.Dance(0) ; 
        }  


        double  bs(){  
                  int l = 0 , r = radiu.size() - 1 , mid , s = 0  ;  
                  while(l <= r){  
                       mid = (l + r) >> 1 ;  
                       if(ok(radiu.get(mid))){  
                           s = mid ;  
                           r = mid - 1 ;  
                       }  
                       else  l = mid + 1 ;  
                  }  
                  return radiu.get(s) ;  
        }  

}

class DLX{
    static final int maxnode = 4000;
    static final int MaxM = 70;
    static final int MaxN = 70;
    static int[] U = new int[maxnode];
    static int[] R = new int[maxnode];
    static int[] L = new int[maxnode];
    static int[] D = new int[maxnode];
    static int[] Row = new int[maxnode];
    static int[] Col = new int[maxnode];
    static int[] H = new int[MaxN] ;
    static int[] S = new int[MaxM] ;
    static boolean[] vis = new boolean[maxnode] ;

    int limit ;
    int n , m , size ;

    DLX(int n , int m , int limit){
        this.n = n;
        this.m = m;
        this.limit = limit ;
        for(int i = 0 ; i <= m ; i++){
            S[i] = 0;
            U[i] = D[i] = i;
            L[i] = i-1;
            R[i] = i+1;
        }
        R[m] = 0; L[0] = m;
        size = m;
        for(int i = 1 ; i <= n ; i++)
            H[i] = -1;
    }

    void Link(int r,int c){
         ++S[Col[++size]=c];
         Row[size] = r;
         D[size] = D[c];
         U[D[c]] = size;
         U[size] = c;
         D[c] = size;
         if(H[r] < 0) H[r] = L[size] = R[size] = size;
         else{
            R[size] = R[H[r]];
            L[R[H[r]]] = size;
            L[size] = H[r];
            R[H[r]] = size;
         }
    }

    void remove(int c){
         for(int i = D[c];i != c;i = D[i]){
            L[R[i]] = L[i];
            R[L[i]] = R[i];
         }    
    }

    void resume(int c){
        for(int i = U[c] ; i != c ; i = U[i])
            L[R[i]] = R[L[i]] = i;
    }

    int f(){
        int ret = 0;
        for(int c = R[0];c != 0;c = R[c]) vis[c] = true;
        for(int c = R[0];c != 0;c = R[c]){
            if(vis[c]){
                ret++;
                vis[c] = false;
                for(int i = D[c];i != c;i = D[i]){
                    for(int j = R[i];j != i;j = R[j])
                        vis[Col[j]] = false;
                }
            }
        }
        return ret;
    }

    boolean Dance(int d){
        if(d + f() > limit) return false;
        if(R[0] == 0) return d <= limit;
        int c = R[0] ;
        for(int i = R[0] ; i != 0 ; i = R[i]){
            if(S[i] < S[c]) c = i;
        }
        for(int i = D[c] ; i != c ; i = D[i]){
            remove(i);
            for(int j = R[i] ; j != i ; j = R[j]) remove(j);
            if(Dance(d+1))return true;
            for(int j = L[i] ; j != i ; j = L[j]) resume(j);
            resume(i);
        }
        return false;
    }
}

class InputReader{
        public BufferedReader  reader;
        public StringTokenizer  tokenizer;

        public InputReader(InputStream stream){
                    reader = new BufferedReader(new InputStreamReader(stream), 32768) ;
                    tokenizer = null ;
        }

        public String next(){
                    while(tokenizer == null || ! tokenizer.hasMoreTokens()){
                        try{
                                tokenizer = new StringTokenizer(reader.readLine());
                        }catch (IOException e) {
                                throw new RuntimeException(e);
                        }
                    }
                    return tokenizer.nextToken();  
        }

        public int  nextInt(){
                    return Integer.parseInt(next());
        }

        public long nextLong(){
                    return Long.parseLong(next());
        }

        public double nextDouble(){
                    return  Double.parseDouble(next());
        }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值