【洛谷p1158】导弹拦截
这道题是个有想法的枚举qwq
注意:此导弹拦截非彼导弹拦截p1020 导弹拦截
一道题是1999年的,然后我们现在要写的是经过11年韬光养晦之后的导弹拦截
SOLUTION:
要不先说一说我错误的贪心防止踩坑?
错误贪心1:40pts:先比较某个点到拦截系统1和2的距离,取距离较小的一个,然后看这个距离是否在当前的工作半径之内,如果在,继续循环,不在的话就更新当前某个拦截系统的工作半径。
显然这个贪心是不对的qwq(用jiaozhitou想想也可以想出来)
now1=now2=0;
for(int i=1;i<=n;i++){ if(d[i].dis1<d[i].dis2){ if(d[i].dis1<=now1) continue; now1=d[i].dis1; } else { if(d[i].dis2<=now2) continue; now2=d[i].dis2; } }
错误贪心2:70pts:应该很多小伙伴都和我一样卡在了70pts,因为这样的贪心是错误的emm:
70pts的贪心就是将错误1的if语句提到了外面,从而使一些可以被直接拦截的直接拦截而不是先取距离较小的一套拦截系统再进行拦截;但是还是有不对的地方(我不知道为什么)
now1=now2=0; for(int i=1;i<=n;i++){ if(now1>d[i].dis1) continue; if(now2>d[i].dis2) continue; if(d[i].dis1<d[i].dis2) now1=d[i].dis1; else now2=d[i].dis2; }
首先显然是输入然后计算某个导弹到拦截系统的距离(这里直接计算平方啦没有再开根)
我比较喜欢写函数和结构体(全局变量我也很爱),所以就以函数的形式求了距离的平方,储存在结构体中。
计算完距离的平方之后,就是十分神奇的枚举了:
首先我们可以将所有的导弹按照距离某一个系统的距离从远到近排列(这里排列系统1),然后先假定所有的导弹都由系统1拦截,计算一个代价,然后依次枚举1~n个导弹由系统2拦截,求一个最小值,即为所求答案;
以下是
CODE:
#include<bits/stdc++.h> using namespace std; int x1,y11,x2,y2,now1,now2,minn; int n; struct node{ int x,y,dis1,dis2; }d[100010]; bool cmp(node x,node y){ return x.dis1>y.dis1; } int jl(int x,int y,int k){ if(k==1) return (x-x1)*(x-x1)+(y-y11)*(y-y11); else return (x-x2)*(x-x2)+(y-y2)*(y-y2); } int main(){ scanf("%d %d %d %d",&x1,&y11,&x2,&y2); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d %d",&d[i].x,&d[i].y); d[i].dis1=jl(d[i].x,d[i].y,1); d[i].dis2=jl(d[i].x,d[i].y,2); } sort(d+1,d+n+1,cmp); now1=d[1].dis1;minn=d[1].dis1; int js=0; for(int i=1;i<=n;i++){ now1=d[i+1].dis1; if(now2<d[i].dis2) now2=d[i].dis2; js=now1+now2; if(js<minn) minn=js; } cout<<minn<<endl; }