用最少圆覆盖所有点问题

问题描述:海面上有一些船需要与陆地进行通信,需要在海岸线上布置一些基站。现将问题抽象为,在x周上方,给出N条船的坐标p1,p2,…,pn,pi=(xi,yi),xi>=0,yi<=d, 1<=i<=N,在x轴安防的基站可以覆盖半径为d的区域内所有点,问在x轴上至少要安放几个点才可以将x轴上方的点都覆盖起来。试设计一个算法求解该问题

设计思路:首先将所有的点按横坐标从小到大进行排序。当点集不空的时候,每次取出最左边的点,将该点视做圆周上的点,以该点到x轴上距离为d的点作为圆心,以d作为半径,画出一个圆,然后去除掉包含在该圆内的点。然后继续选出一个最左的点,重复以上操作,直至点集为空,表示所有点都被覆盖,此时得出的圆的个数就是所求答案.


Alogrithm:

          Sort(list)

          Repeat

              Point p = the most left Point

              centX =  p.getX() +Math.sqrt(Math.pow(d,2)-Math.pow(p.getY(),2))//圆心横坐标,计算出x轴上某点与p的距离为d的点的横坐标 

               count++

             For all point po

                 If

                   p.getDistance(po) <=d

                   list.remove(po)

            Until list==null


运行结果:




import java.text.DecimalFormat;
import java.util.Comparator;

/**
 * Created by Administrator on 2016/11/29.
 */
public class Point implements Comparable
     
     
      
       {
    private double x ;
    private double y ;

    public void setX(double x) {
        this.x = x;
    }

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    @Override
    public String toString() {
        DecimalFormat de = new DecimalFormat("0.00");
        return "Point{" +
                "x=" + de.format(x) +
                ", y=" + de.format(y) +
                '}';
    }

    public void setY(double y) {
        this.y = y;
    }

    public Point() {
    }

    public Point(double x, double y) {

        this.x = x;
        this.y = y;

    }

    public double getDistance(Point o){
        double distance = Math.sqrt(Math.pow(x-o.getX(),2)+Math.pow(y-o.getY(),2));
        return distance;
    }
    @Override
    public int compareTo(Point o) {
        return (int) (this.x - o.getX());
    }
}
import java.lang.reflect.Array;
import java.util.*;

/**
 * Created by Administrator on 2016/11/29.
 */
public class pointCover {
    public static int count= 0 ;
    public static int d = 4;
    public static void main(String[] agrs){
        List
      
      
       
        list = new ArrayList<>();
        list.add(new Point(-10,4));

        list.add(new Point(7,3.5));
       ;
        list.add(new Point(5,3.1));
        list.add(new Point(1,2));
        list.add(new Point(-4,3));

        list.add(new Point(-2,4));
        Collections.sort(list);//按横坐标进行排序
        System.out.println("所有的点为:");
        for(Point op : list)
            System.out.print(op+"  ");
        System.out.println();
        List
       
       
        
         result = new ArrayList<>();//保存求出的圆的点

        Point p;
        while( (p = getTop(list))!=null ){//取出最左边的点
            //
            double centX = p.getX() + Math.sqrt(Math.pow(d,2)-Math.pow(p.getY(),2));//计算圆心的横坐标
            Point centerP = new Point(centX,0);//圆心的纵坐标为0
            result.add(centerP);
            count++;//圆的数量为0
            Iterator
        
        
         
          it = list.iterator();
            while(it.hasNext()){
                if(centerP.getDistance(it.next())<=d)
                    it.remove();
            }
        }

        System.out.println("圆的数量为:"+count);
        System.out.print("圆心分别为");
        for(Point o : result)
            System.out.print(" "+o);
        System.out.println();
        System.out.println("半径为:"+d);





    }

    public static Point getTop(List
         
         
           list){ if(list.size()>0) return list.get(0); else return null; } } 
         
        
        
       
       
      
      
     
     


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值