NOIP2010普及組 導彈攔截(重慶一中高2018級信息學競賽測驗3) 解題報告

做題思路(錯解):剛拿到這道題時,想得過於複雜,用了兩個不同的結構體來存導彈的座標和導彈到系統的距離的平方和,在存平方和時還把導彈的到兩個系統的距離分開存了,本來是想按導彈到系統的距離的平方和由小到大排序來計算最小代價,用下標和是到哪個系統的標記來控制不選擇重複的導彈,結果發現在計算最小代價時特殊情況太多,並且對於一些數據仍有問題。


解題思路(正解):根據題意,我們可以只定義一個結構體存每個導彈的座標和到兩個系統的距離的平方和。先按照導彈到第一個系統的距離的平方和由小到大排序,從到第一個系統距離最大的導彈開始,枚舉第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;
}

考後反思:在存儲數據時,儘量越簡單越好,存得複雜之後就會產生較多的特殊情況需要判斷。
發佈了57 篇原創文章 · 獲贊 8 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章