hdu4145 Cover The Enemy(贪心+枚举)

本文探讨了在给定两座炮塔坐标和士兵坐标的情况下,如何通过优化算法来确定炮塔覆盖范围(半径),以最小化两座炮塔的覆盖面积。通过分析初始错误思路和正确策略,提出了一种有效的解决方法。具体步骤包括:首先对士兵按距离炮塔的远近进行排序;接着,以每个士兵为起点,枚举可能的覆盖范围,最终确定两座炮塔的最优半径,从而实现最小覆盖面积的目标。

题意:已知两座炮塔的坐标,以及n个士兵的坐标,以两座炮塔A,B为圆心,R1,R2为半径,可覆盖所有士兵的坐标,求R1^2+R2^2最小值。

思路:

这道题开始的思路是:

枚举每个敌人,比较它到2个炮塔的距离,如果距离A近,则把这个距离与上个距离A近的敌人的距离比较,取较大者。反之同理处理B。这样就得到A和B炮的半径,进而得到答案。


但是这样是错的。若AB距离为20,他们中点旁有2个士兵,依据该思路得到的答案为9* 9+ 9 * 9 = 162,而如果只用A,则只需要11 * 11 = 121.所以这种思路是错误的。


靠谱的思路应该是:

将所有士兵离A的距离升序排序,然后枚举A的半径,则B的半径就是A无法覆盖的点中离B最远的距离。然后用一个变量储存中间变量距离A和B之和的最小值即可。


代码如下:

/*
*Author : Flint_x 
*Created Time : 2015-05-14 12:31:03 
*File name : 514j.cpp 
*/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const double eps(1e-8);
typedef long long lint;

const int N = 100000;

struct enemy{
	int x,y;
	int da,db;
}e[N]; 

bool cmp(enemy a , enemy b){
	return a.da > b.da;
}
int main(){
//    freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
	int T;
	cin >> T;
	for(int t = 1 ; t <= T ; t++){
		int x1,y1,x2,y2;
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		int n;
		scanf("%d",&n);
		for(int i = 1 ; i <= n ; i++){
			int x_,y_;
			scanf("%d%d",&x_,&y_);
			lint s1,s2;
			s1 = (x_-x1)*(x_-x1) + (y_-y1)*(y_-y1);
			s2 = (x_-x2)*(x_-x2) + (y_-y2)*(y_-y2);
//			cout << s1 << endl;
//			cout << s2 << endl;]
			e[i].x = x_;
			e[i].y = y_;
			e[i].da = s1;
			e[i].db = s2;
		}
		sort(e+1 , e+n+1 , cmp);
		int ans = e[1].da;
		int tmp = 0;
		for(int i = 2 ; i <= n ; i++){
			tmp = max(tmp , e[i-1].db);
			ans = min(ans , tmp + e[i].da);
		}
		tmp = max(tmp , e[n].db);
		ans = min(ans , tmp);
		 printf("%d\n", ans); 
	}

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值