• 导弹拦截 贪心


    链接:https://ac.nowcoder.com/acm/problem/16601?&headNav=acm
    来源:牛客网

      经过11年的韬光养晦,某国研发出了一种新的导弹拦截系统,凡是与它的距离不超过其工作半径的导弹都能够被它成功拦截。当工作半径为0时,则能够拦截与它位置恰好相同的导弹。但该导弹拦截系统也存在这样的缺陷:每套系统每天只能设定一次工作半径。而当天的使用代价,就是所有系统工作半径的平方和。

        某天,雷达捕捉到敌国的导弹来袭。由于该系统尚处于试验阶段,所以只有两套系统投入工作。如果现在的要求是拦截所有的导弹,请计算这一天的最小使用代价。

     

    输入描述:

    第一行包含4个整数x1、y1、x2、y2,每两个整数之间用一个空格隔开,表示这两套导弹拦截系统的坐标分别为(x1, y1)、(x2, y2)。

    第二行包含1个整数N,表示有N颗导弹。接下来N行,每行两个整数x、y,中间用一个空格隔开,表示一颗导弹的坐标(x, y)。不同导弹的坐标可能相同。

    输出描述:

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

    输入

    复制
    0 0 10 0
    2
    -3 3
    10 0

    输出

    复制
    18

    说明

    要拦截所有导弹,在满足最小使用代价的前提下,两套系统工作半径的平方分别为18和0。
    示例2

    输入

    复制
    0 0 6 0 
    5 
    -4 -2 
    -2 3 
    4 0 
    6 -2 
    9 1

    输出

    复制
    30

    说明

    样例中的导弹拦截系统和导弹所在的位置如下图所示。要拦截所有导弹,在满足最小使用代价的前提下,两套系统工作半径的平方分别为20和10。
     
     

    备注:

    两个点(x1, y1)、(x2, y2)之间距离的平方是(x1−x2)2+(y1−y2)2

    两套系统工作半径r1、r2的平方和,是指r1、r2分别取平方后再求和,即r12+r22

    对于10%的数据,N=1

    对于20%的数据,1≤N≤2

    对于40%的数据,1≤N≤100

    对于70%的数据,1≤N≤1000

    对于100%的数据,1≤N≤100000,且所有坐标分量的绝对值都不超过1000。

    这是一个贪心问题:

    基本思路:

    先求出每个点到两个原点的距离,其次对s1进行排序(或者s2),之后的一个for循环非常重要!!!

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const ll maxn = 1e6;
    struct node
    {
        int x,y;
        ll s1,s2;
    }exa[maxn];
    bool cmp1(node a,node b)
    {
        return a.s1>b.s1;
    }
    ll ans=(1<<30),t;
    int main()
    {
        int x1,y1,x2,y2;
        int n;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        cin>>n;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&exa[i].x,&exa[i].y);
            exa[i].s1=(exa[i].x-x1)*(exa[i].x-x1)+(exa[i].y-y1)*(exa[i].y-y1);
            exa[i].s2=(exa[i].x-x2)*(exa[i].x-x2)+(exa[i].y-y2)*(exa[i].y-y2);
        }
        sort(exa,exa+n,cmp1);
        for(int i=0;i<n;i++)//ans和t是两个结果
        {
            ans=min(ans,exa[i].s1+t);//ans表示:第i个点是到1号或者2号,求出最小的值(可以看作一种选择)
            t=max(t,exa[i].s2);//t表示所有的点都到2号点,这时候最大的圆
        }//注意一下:第一次循环后,ans的值就是所有的点到1号位置的最大的圆的半径平方。
        cout<<min(ans,t)<<endl;
        return 0;
    }
    

      

  • 相关阅读:
    leetcode231 2的幂 leetcode342 4的幂 leetcode326 3的幂
    leetcode300. Longest Increasing Subsequence 最长递增子序列 、674. Longest Continuous Increasing Subsequence
    leetcode64. Minimum Path Sum
    leetcode 20 括号匹配
    算法题待做
    leetcode 121. Best Time to Buy and Sell Stock 、122.Best Time to Buy and Sell Stock II 、309. Best Time to Buy and Sell Stock with Cooldown 、714. Best Time to Buy and Sell Stock with Transaction Fee
    rand7生成rand10,rand1生成rand6,rand2生成rand5(包含了rand2生成rand3)
    依图
    leetcode 1.Two Sum 、167. Two Sum II
    从分类,排序,top-k多个方面对推荐算法稳定性的评价
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/10296359.html
Copyright © 2020-2023  润新知