zoukankan      html  css  js  c++  java
  • NOIP2010普及组 导弹拦截

    导弹拦截

    OJ地址:
    https://www.luogu.org/problemnew/show/P1158
    http://codevs.cn/problem/1128/
     
    题目描述 Description

    经过11 年的韬光养晦,某国研发出了一种新的导弹拦截系统,凡是与它的距离不超过其工作半径的导弹都能够被它成功拦截。当工作半径为0 时,则能够拦截与它位置恰好相同的导弹。但该导弹拦截系统也存在这样的缺陷:每套系统每天只能设定一次工作半径。而当天的使用代价,就是所有系统工作半径的平方和。
    某天,雷达捕捉到敌国的导弹来袭。由于该系统尚处于试验阶段,所以只有两套系统投入工作。如果现在的要求是拦截所有的导弹,请计算这一天的最小使用代价。

    数据范围
    对于10%的数据,N = 1
    对于20%的数据,1 ≤ N ≤ 2
    对于40%的数据,1 ≤ N ≤ 100
    对于70%的数据,1 ≤ N ≤ 1000
    对于100%的数据,1 ≤ N ≤ 100000,且所有坐标分量的绝对值都不超过1000。

    输入描述 Input Description

    第一行包含4 个整数x1、y1、x2、y2,每两个整数之间用一个空格隔开,表示这两套导弹拦截系统的坐标分别为(x1, y1)、(x2, y2)。
    第二行包含1 个整数N,表示有N 颗导弹。接下来N 行,每行两个整数x、y,中间用一个空格隔开,表示一颗导弹的坐标(x, y)。不同导弹的坐标可能相同。

    输出描述 Output Description

    输出只有一行,包含一个整数,即当天的最小使用代价。

    样例输入 Sample Input

    0 0 10 0
    2
    -3 3
    10 0

    样例输出 Sample Output

    18

    数据范围及提示 Data Size & Hint

    两个点(x1, y1)、(x2, y2)之间距离的平方是(x1− x2)^2+(y1−y2)^2。
    两套系统工作半径r1、r2 的平方和,是指r1、r2 分别取平方后再求和,即r1^2+r2^2。

    【样例说明】

    样例1中要拦截所有导弹,在满足最小使用代价的前提下,两套系统工作半径的平方分别为180

    算法分析

    参考

    https://blog.csdn.net/yuyanggo/article/details/48739029

    http://hzwer.com/44.html

    假设两个导弹系统为p1、p2,那么我们可以通过枚举两个导弹系统的半径,寻找最小值消耗值。

    导弹系统的半径必然是系统所在位置与某一导弹的连线,基于此,p1的可能半径就只有n种,现在的问题就是枚举p1的半径之后,如何得到p2的半径呢?

    我们把所有的导弹按其坐标点到p1的距离从大到小进行排序,若选择 k 号点到p1的距离作为半径,那么k点之后的点都能被p1击落。而k点之前的点p1是无法拦截的,只能由p2击落,于是,p2的半径即为前 k-1个点到 p2 的最大半径。
    这道题有一个难点:如何寻找“前 k-1个点到 p2 的最大半径”。若是每当确定k点位置后,再来一次循环去寻找前k-1个点到p2的最大距离,那么整个算法的时间复杂度将会达到N^2级别,提交OJ时会超时。如何解决呢?

    其实,上述算法描述中已经隐约暗示了解决方式。上述算法描述中,为何非要从距离p1最远的那个点开始枚举k呢?从距离p1最远的点开始枚举,一开始的时候p1负责拦截所有导弹,p2是不拦截任何导弹的,也就是p2的工作半径是0.然后随着枚举的继续,k每次挪动一个位置,p2拦截的导弹也会增多一枚。仅仅增多一枚导弹,很容易判断出新状态下p2拦截区域的最大工作半径。所以,必须要让p2一开始是不拦截任何导弹,然后p2拦截的导弹数量逐渐增加。

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 struct obj
     4 {
     5     int d1,d2; //d1和d2分别表示某一个导弹距离p1和p2的距离的平方 
     6 };
     7 int cmp(const void *a,const void *b)//按照D[i].d1从大到小排序 
     8 {
     9     struct obj *x,*y;
    10     x=(struct obj*)a;
    11     y=(struct obj*)b;
    12     return y->d1 - x->d1;
    13 }
    14 int main(int argc, char *argv[])
    15 {
    16     int x1,y1,x2,y2,x,y,N;
    17     struct obj D[100005];//存储所有的导弹 
    18     int i,j;
    19     int r1,r2,cost,minCost=-1;
    20     
    21     scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    22     scanf("%d",&N);
    23     for(i=0;i<N;i++)
    24     {
    25         scanf("%d%d",&x,&y);
    26         D[i].d1=(x-x1)*(x-x1)+(y-y1)*(y-y1);
    27         D[i].d2=(x-x2)*(x-x2)+(y-y2)*(y-y2);
    28     }
    29     
    30     qsort(D,N,sizeof(D[0]),cmp);//按照D[i].d1从大到小排序    
    31     /*for(i=0;i<N;i++)
    32         printf("%d %d
    ",D[i].d1,D[i].d2);*/
    33     
    34     //第一种极限情况:所有导弹均由p1系统拦截 
    35     r2=0;
    36     r1=D[0].d1;
    37     minCost=r1+r2;
    38     
    39     r2=D[0].d2;
    40     for(i=1;i<N;i++)//从D[0]~D[i-1]由p2拦截,D[i]~D[n-1]由p1拦截 
    41     {
    42         r1=D[i].d1;
    43         if(r2<D[i-1].d2) r2=D[i-1].d2;
    44         cost=r1+r2;
    45         if(cost<minCost) minCost=cost;
    46     }
    47     
    48     //第二种极限情况:所有导弹均由p2拦截 
    49     r1=0;
    50     if(r2<D[N-1].d2) r2=D[N-1].d2;
    51     cost=r1+r2;
    52     if(cost<minCost) minCost=cost;
    53     
    54     printf("%d
    ",minCost);        
    55     return 0;
    56 }

    下面这个代码比较简洁,可以参考一下。

    设拦截系统为 a , b

    按照导弹到其中一个拦截系统 a 的距离排序,将离 a 最近的 i 个导弹都交给 a ,其余给 b

    倒序枚举断点,每次更新答案

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 #define inf 1000000000
     7 #define ll long long
     8 
     9 struct data
    10 {
    11     int x,y,s1,s2;
    12 }a[100005];
    13 
    14 int n,x1,y1,x2,y2;
    15 int mn=inf;
    16 
    17 bool cmp(data a,data b)//结构体比较函数,可以理解为定义小于号,即a.s1<b.s1时return 1 否则return 0
    18 {
    19     return a.s1<b.s1;
    20 }
    21 int main()
    22 {
    23     scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    24     scanf("%d",&n);
    25     for(int i=1;i<=n;i++)
    26     {
    27         scanf("%d%d",&a[i].x,&a[i].y);
    28         a[i].s1=(a[i].x-x1)*(a[i].x-x1)+(a[i].y-y1)*(a[i].y-y1);//计算距离。注意:这里没有开平方 
    29         a[i].s2=(a[i].x-x2)*(a[i].x-x2)+(a[i].y-y2)*(a[i].y-y2);        
    30     }
    31     sort(a+1,a+n+1,cmp);//对a[1]~a[n]进行排序,按照a[i].s1升序排序 
    32     
    33     int rb=0;
    34     a[n+1].s2=0;
    35     for(int i=n;i>0;i--)//从离a最远的导弹开始枚举
    36     {
    37         rb=max(a[i+1].s2,rb);//将i+1号导弹交给系统b,更新系统b的半径
    38         mn=min(mn,a[i].s1+rb);//更新答案
    39     }
    40     
    41     //一种极限情况 
    42     rb=max(a[1].s2,rb);//将所有导弹交给系统b,更新系统b的半径
    43     mn=min(mn,0+rb);//更新答案
    44     
    45     printf("%d",mn);
    46     return 0;
    47 }
  • 相关阅读:
    DedeCMS Xss+Csrf Getshell dedefile_manage_control.php
    dedeCMS /plus/ad_js.php、/plus/mytag_js.php Vul Via Injecting PHP Code By /plus/download.php Into DB && /include/dedesql.class.php
    phpMyadmin /scripts/setup.php Execute Arbitrary PHP Code Via A Crafted POST Request CVE-2010-3055
    Linux inode && Fast Directory Travel Method(undone)
    Linux进程自保护攻防对抗技术研究(Process Kill Technology && Process Protection Against In Linux)
    PHP Web System Optimization(undone)
    PHP Simulation HTTP Request(undone)
    Server Data Synchronization Via Linux rsync、rsync+inotify Between Load Balance Server
    Ecshop /admin/get_password.php Password Recovery Secrect Code Which Can Predict Vulnerability
    Dedecms includedialogselect_soft_post.php Upload Any Files To The Specified Directory Via Variable Not Initial Flaw Bypass Extension Defence
  • 原文地址:https://www.cnblogs.com/huashanqingzhu/p/10461604.html
Copyright © 2011-2022 走看看