您的位置:首页 > 编程语言 > C语言/C++

NOIP2010普及组 导弹拦截(重庆一中高2018级信息学竞赛测验3) 解题报告

2016-07-25 11:57 369 查看


做题思路(错解):刚拿到这道题时,想得过于复杂,用了两个不同的结构体来存导弹的坐标和导弹到系统的距离的平方和,在存平方和时还把导弹的到两个系统的距离分开存了,本来是想按导弹到系统的距离的平方和由小到大排序来计算最小代价,用下标和是到哪个系统的标记来控制不选择重复的导弹,结果发现在计算最小代价时特殊情况太多,并且对于一些数据仍有问题。

解题思路(正解):根据题意,我们可以只定义一个结构体存每个导弹的坐标和到两个系统的距离的平方和。先按照导弹到第一个系统的距离的平方和由小到大排序,从到第一个系统距离最大的导弹开始,枚举第i个导弹时,先将第i+1个导弹(到第一个系统距离比第i个导弹远)交给第二个系统拦截,更新第二个系统的工作半径,然后答案从已有答案和当前第二个系统的工作半径加上第i个导弹到第一个系统距离的平方和(第一个系统的工作半径)取最小值。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100005;
const int inf=1000000010;
int X1,Y1,X2,Y2,N;
struct data
{
int x,y,s1,s2;
};
data a[maxn];
bool cmp(data aa,data bb)
{
return aa.s1<bb.s1;
}
int main()
{
freopen("missilery.in","r",stdin);
//freopen("missilery.out","w",stdout);
scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2);
scanf("%d",&N);
for(int i=1;i<=N;i++)
scanf("%d%d",&a[i].x,&a[i].y);
for(int i=1;i<=N;i++)
{
a[i].s1=(a[i].x-X1)*(a[i].x-X1)+(a[i].y-Y1)*(a[i].y-Y1);
a[i].s2=(a[i].x-X2)*(a[i].x-X2)+(a[i].y-Y2)*(a[i].y-Y2);
}
sort(a+1,a+1+N,cmp); //按导弹到第一个系统的距离的平方和由小到大排序
int ans=inf,a2=0;
for(int i=N;i>=0;i--)
{
a2=max(a2,a[i+1].s2); //更新第二个系统的工作半径
ans=min(ans,a[i].s1+a2); //更新答案
}
printf("%d\n",ans);
return 0;
}

考后反思:在存储数据时,尽量越简单越好,存得复杂之后就会产生较多的特殊情况需要判断。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ NOIP 2010