• P1158 导弹拦截


    P1158 导弹拦截

    题解

    这不是一道简单的贪心,他还要枚举

    我们首先要计算出导弹距离距离两个拦截系统分别的距离

    then,假设由一个拦截系统把它们全部拦截,然后逐一枚举导弹

    如果另一个拦截系统距离它更近我们显然是要更新的

     r1 表示拦截系统1的半径平方

     r2 表示拦截系统2的半径平方

    我们假设第一个拦截系统把它们全部拦截

    按照导弹与拦截系统1 的距离从小到大排序,然后从大到小枚举

    这样距离拦截系统1最远的导弹就被放在了最后面,但是不确定距离拦截系统2的距离

    (其实这样sort下来就相当于维护了一个前缀和,a[ i ].chang1表示拦截前 i 个导弹需要的最小 r1)

    那么 r1 一开始一定是等于 a[ n ].chang1

    从大到小枚举:

    假设现在有导弹 i ,它被拦截系统2拦截(前提是超出 r2 的拦截范围),那么前 i 个导弹一定都是被拦截系统2拦截(否则的话,根本就不会更新啊),那么剩下的导弹被拦截系统1 拦截,计算出此时的结果,与先前的结果比较,求解一个最小值

    最后还要比较一下更新 ans 和 r1 ,单个拦截更优还是两个一起拦截更优 

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cstring>
    #include<cmath>
    #include<bits/stdc++.h>
    
    using namespace std;
    
    int x1,yi,x2,y2,x,y,n;
    int r1,r2,ans=1e9+6;
    
    struct node
    {
        int chang1,chang2;
    }a[100001];
    
    bool cmp(node x,node y)
    {
        return x.chang1 <y.chang1 ;
    }
    
    int main()
    {
        scanf("%d%d%d%d%d",&x1,&yi,&x2,&y2,&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            a[i].chang1 =(x-x1)*(x-x1)+(y-yi)*(y-yi);
            a[i].chang2 =(x-x2)*(x-x2)+(y-y2)*(y-y2);
        }
        
        sort(a+1,a+n+1,cmp);
        
        r1=a[n].chang1 ;
        
        for(int i=n-1;i>=1;i--)
        {
            if(r2<a[i+1].chang2 ) r2=a[i+1].chang2 ;
            ans=min(ans,a[i].chang1 +r2);
        }
        
        printf("%d",min(ans,r1));
        
    }
  • 相关阅读:
    二分查找小结
    FZU みねちゃんの修罗场(从一堆出现三次的数中找出出现两次的数)
    《C陷阱与缺陷》杂记
    HDU 1846 Brave Game(巴什博弈)
    【转载】并查集详解
    第七次作业——学末总结
    STL之vector
    fzuoop期中练习
    MFC 文件对话框
    第六次作业——利用MFC实现计算器图形界面以及简单四则运算表达式批处理
  • 原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/11028815.html
Copyright © 2020-2023  润新知