【排序+贪心】导弹拦截 luogu-1158

题目描述

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

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

分析

我们将一个导弹距离两个拦截装置的距离算出来,在按照距离第一个装置的距离为关键字排序(按照第二个的也一样的),从小到大排序,在从最后一个,也就是距离第一个装置距离最长的导弹开始,比较距离第二个装置的距离。
因为我们要算出最少的代价,也就是要算出最少的距离第一个和第二个装置的长度,那么我们如果找到当前的距离第二个装置的距离比当前的最小值要小,那么就把当前的最小值替换掉,然后算如果要覆盖当前这个导弹所代价,在和答案的最小的值进行比较,就可以了。

AC代码

#include <bits/stdc++.h>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const int maxn=100005;
const int inf=1<<30;
int X1,X2,Y1,Y2;
int n;
struct syste{
    int r1,r2;
}Missile[maxn];
int calc(int X1,int Y1,int X2,int Y2) {
    return (X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2);
}
inline int read() {
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
inline bool cmp (syste a,syste b) {
    return a.r1<b.r1;
}
int main(int argc,char* argv[]){
    X1=read(),Y1=read(),X2=read(),Y2=read(),n=read();
    for (int i=1;i<=n;i++) {
        int x=read(),y=read();
        Missile[i].r1=calc(x,y,X1,Y1);
        Missile[i].r2=calc(x,y,X2,Y2);
    }
    sort(Missile+1,Missile+1+n,cmp);
    int tmp=0,ans=inf;
    for (int i=n;i>=1;i--) {
        tmp=max(tmp,Missile[i+1].r2);
        ans=min(ans,Missile[i].r1+tmp);
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Dawn-Star/p/9695718.html