zoukankan      html  css  js  c++  java
  • 解题报告 Sadar

     

    1.        题目

    3.Sadar             

    题目描述:

    假设海岸线是一条直线,大海在海岸线的一侧(纵坐标为非负),每个小岛都是海中的一个点,现在在海岸线上安装雷达,所安装的雷达型号相同,即每个雷达所能检测到的范围都是等大的(雷达的检测范围是半径为d的圆)。已知雷达只能建在海岸线上,现在给你n个岛的坐标,假设海岸线为坐标系的x轴,求出最少要建造多少个雷达才能监测到所有的小岛(每个小岛可以被多个雷达监测)。

    输入:

      输入多组数据。

    对于每组数据,第一行输入两个正整数n,d ,分别代表小岛的个数和雷达监测的半径

    接下来有n行,每行两个整数x,y  代表小岛的横纵坐标

    输出:

      对于每组数据,输出最小所需的雷达数,若无法覆盖所有的小岛,输出-1

    数据范围:

      n<=1000

      -maxlongint<=x<=maxlongint

    样例:

    输入:

    3 2

    1 2

    -3 1

    2 1

    1 2

    0 2

    输出:

    2

    1

     

    2.        题目实质

    还记得那个点覆盖区间的贪心不?

    3.        算法

    贪心。

    首先,预处理一下,计算出包含这个点的圆的圆心在哪个区间里,则圆心在这个区间里的圆一定可以包含这个点,这样就转换成了,选取最少的点,使每个区间里都至少有一个点。(如果一个点只能包含一次,那就只能用动规了)

    然后关于这个经典模型,这里提供三种解法:

           按终点排序,从小到大,选取每一个没有点的区间的右端点(易证,右端点最易在下一个区间内)。

           按起点倒序排序,从大到小,选取每一个没有点的区间的右端点。

           按起点排序,当一个区间包含另一个区间时,将比较大的那个区间的 y 值赋为较小的区间的 y 值(易证,如果一个点在一个较小的区间里,且一个较大的区间包含这个较小的区间,则这个点一定在那个较大的区间里)。然后再依次选取每个区间的右端点,当后一个区间与前一个区间不包含也不交叉时,将答案加一。

    以上三种方法,都是为了避免区间相互包含的情况。

    然后就是这样。

    4.        注意事项

    这个题不是计算几何。

    其实,比较难的动规题,是可以用贪心骗分的。

    5.        程序代码

    Leve  第三种贪心 Pascal

    var

     x,y:array[1..1000] of double;

     n,i,j,d,ans,max,xxx,yyy:longint;

     tou:double;

    procedure qs(r,l:longint);

     var

      i,j:longint;

      xx,yy :double;

     begin

      i:=r; j:=l;

      xx:=x[(i+j)>>1];

      repeat

       while x[i]<xx do inc(i);

       while x[j]>xx do dec(j);

       if i<=j then

        begin

            yy:=x[i]; x[i]:=x[j]; x[j]:=yy;

            yy:=y[i]; y[i]:=y[j]; y[j]:=yy;

             inc(i);

            dec(j);

           end;

       until i>j;

     if i<l then qs(i,l);

     if j>r then qs(r,j);

    end;

    begin

     assign(input,'radar.in');

     assign(output,'radar.out');

     reset(input);

     rewrite(output);

      readln(n,d);

     while (n<>0) and (d<>0) do

     begin

     max:=0;

     for i:=1 to n do

      begin

      readln(xxx,yyy);

      if yyy>max then max:=yyy;

      if yyy>d then

      begin

       for j:=i+1 to n do

        readln(xxx,yyy);

        break;

       end;

      x[i]:=xxx-sqrt(sqr(d)-sqr(yyy));

      y[i]:=xxx+sqrt(sqr(d)-sqr(yyy));

      end;

     if max>d then

     begin

      writeln('-1');

     end

     else

     begin

     ans:=1;

     qs(1,n);

     tou:=y[1];

     for i:=2 to n do

      if y[i]<tou then

       begin

        tou:=y[i];

     

       end

      else

       if x[i]>tou then

       begin

       tou:=y[i];

       inc(ans);

       end;

    writeln(ans);

    end;

     

    readln(n,d);

    end;

     close(input);

     close(output);

    end.

     

     

     

     

     

  • 相关阅读:
    移动web技能总结
    canvas绘图基础
    如何自定义滚动条?
    学习笔记-AngularJs(十)
    学习笔记-AngularJs(九)
    硬盘杀手!Windows版Redis疯狂占用C盘空间【转】
    64位win10系统无法安装.Net framework3.5的两种解决方法【转】
    分享一个电子书地址
    阿里、腾讯、百度、华为、京东、搜狗和滴滴最新面试题汇集【转】
    jQuery时间轴
  • 原文地址:https://www.cnblogs.com/SueMiller/p/2135164.html
Copyright © 2011-2022 走看看