张三的雷达:C++用贪心算法解POJ1328_Radar Installation问题

POJ1328 Radar Installation

题目链接:
POJ1328 Radar Installation

简单理解一下题目:
张三所在的地方有一个无限延伸的海岸线,如图所示(图源自题目),
图源自题目
x轴上方是海,下方是陆地,海上有一些分散的小岛,张三为了保证每一个小岛都在监测范围内,要在海岸线上放一些雷达,每个雷达的探测范围是直径为d的圆形区域,由于张三比较抠,他想尽可能用比较少的雷达来探测所有的小岛,那么在给定小岛个数n、位置以及探测范围d的情况下,请你算出最少的雷达数,如果无法保证所有小岛都探测到就输出-1。

简单分析:
这个题我一开始的算法是把每个小岛按照横坐标从左至右来排序,然后从最左边的小岛开始,以小岛为圆心画圆,与x轴的右交点作为雷达的位置,因为我想着雷达放在越靠右的位置就越能覆盖右侧的小岛,如果下一个小岛不在上一个小岛的圆圈内就重新设置一个雷达。但是这个方案WA了,试了好半天都不知道为啥错了。后来看到Discuss里面大佬提供的样例,在纸上画了一下就发现了问题所在,如图,例如样例是A(-5,3),B(-3,5)这两个点,按照上述算法,这两个点需要两个雷达,分别是C(-1,0)和D(-3,0),因为如果在A距离最远的地方C设置雷达,由于B点纵坐标太高,不在该范围内,如果把第一步的雷达往左一点,放在D就可以覆盖两座小岛。
草稿纸图,将就看
然后换了一个思路,对每一个小岛求出以其为圆心的圆与x轴的左交点和右交点,然后按照左交点排序,这样比较的时候就不会发生上述思路中排序在后面的小岛对应的雷达位置比前面小岛还靠前的问题,然后如果某一小岛圆圈左交点在前一个小岛的右交点左边,那么该小岛不必新设置一个雷达。

AC代码:(样例来自于Discuss中的大佬,如果都过了基本就对了,正确输出也在最后)

#include<iostream>
#include<algorithm>
#include<math.h>

using namespace std;

const int MAX_N = 100000;

int n, d;
int index = 1;

struct node {
	double x, y;
	double left,right;//圆与x轴焦点坐标
};

node coor[MAX_N];

bool cmp(node a, node b)
{
	return a.left < b.left;
}

void solve()
{
	index = 1;
	sort(coor, coor + n, cmp);
	node temp = coor[0];
	for (int i = 1; i < n; i++)
	{
		if (coor[i].left >temp.right)
		{
			index++;
			temp = coor[i];
		}
		else if (coor[i].right < temp.right)
		{
			temp = coor[i];
		}
	}
}

int main()
{
	int count = 1;
	while (true)
	{
		bool flag = true;
		cin >> n >> d;
		if (n == 0 && d == 0)
			break;
		else
		{
			for (int i = 0; i < n; i++)
			{
				cin >> coor[i].x >> coor[i].y;
				if (abs(coor[i].y) > d)
				{
					flag = false;
				}
				coor[i].left = coor[i].x - sqrt(d * d - coor[i].y * coor[i].y);
				coor[i].right = coor[i].x + sqrt(d * d - coor[i].y * coor[i].y);
			}
			if (flag == true) {
				solve();
				cout << "Case " << count << ": " << index << endl;
				count++;
			}
			else {
				cout << "Case " << count << ": " << -1 << endl;
				count++;
			}
		}
	}
	return 0;
}

/*
3 2
1 2
-3 1
2 1

1 2
0 2

1 2
0 3

0 0


2 5
-3 4
-6 3


4 5
-5 3
-3 5
2 3
3 3

20 8
-20 7
-18 6
-5 8
-21 8
-15 7
-17 5
-1 5
-2 3
-9 6
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 7
9 6
10 5
0 0

2 3
0 2
2 3

2 3
0 2
1 3

3 3
1 2
-3 2
2 4

8 5
2 4
-4 4
-3 3
-3 1
-3 0
-1 0
0 5
6 0

3 0
1 2
-3 1
2 1

3 2
1 2
-3 1
2 1

1 2
0 2


2 3
0 2
2 3

4 -5
4 3
4 3
2 3
6 -9



3 -3
1 2
-3 2
2 1

6 2
1 2
1 2
1 2
-3 1
2 1
0 0

1 2
0 2

2 3
0 2
1 3

3 10
1 10
2 3
4 5

3 5
1 10
2 3
4 5

4 7
1 10
2 3
4 5
0 0

3 9
1 10
2 3
4 5
0 0
*/
/*正确输出:
Case 1: 1
Case 2: 2
Case 3: 4
Case 4: 1
Case 5: 1
Case 6: -1
Case 7: 3
Case 8: -1
Case 9: 2
Case 10: 1
Case 11: 1
Case 12: -1
Case 13: -1
Case 14: 2
Case 15: 1
Case 16: 1
Case 17: 1
Case 18: -1
Case 19: -1
Case 20: -1
*/

做题心得:
这个题一开始交上去的时候显示Complie Error,好半天都没解决,崩溃, 具体错误如图:
在这里插入图片描述
后来我干脆把pow函数去掉,直接用乘法代替了就没有编译错误了,有大佬知道为啥错了可以指点一下嘛,小的感激不尽。编译错误解决后又一直WA,后来发现是算法错了,改了算法之后,再改一些小错误,就AC了。
最后,感谢查阅,欢迎批评指正~

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值