算法2:贪心算法

写在前面:本文记录一些贪心算法的练习题,欢迎讨论!本系列系本人原创,如需转载或引用,请注明原作者及文章出处。本文持续更新。

一、Radar Installation (POJ1328)
描述 Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point locating in the sea side. And any radar installation, locating on the coasting, can only cover d distance, so an island in the sea can be covered by a radius installation, if the distance between them is at most d.
We use Cartesian coordinate system, defining the coasting is the x-axis. The sea side is above x-axis, and the land side below. Given the position of each island in the sea, and given the distance of the coverage of the radar installation, your task is to write a program to find the minimal number of radar installations to cover all the islands. Note that the position of an island is represented by its x-y coordinates.

Figure A Sample Input of Radar Installations
输入
The input consists of several test cases. The first line of each case contains two integers n (1<=n<=1000) and d, where n is the number of islands in the sea and d is the distance of coverage of the radar installation. This is followed by n lines each containing two integers representing the coordinate of the position of each island. Then a blank line follows to separate the cases.
The input is terminated by a line containing pair of zeros。
输出
For each test case output one line consisting of the test case number followed by the minimal number of radar installations needed. "-1" installation means no solution for that case.
样例输入 3 2 1 2 -3 1 2 1
1 2 0 2
0 0
样例输出
Case 1: 2 Case 2: 1
解析
题目中文描述:假定海岸线是无限长的直线,陆地在海岸线的一边,大海在另一边,每个小岛都视为坐落在海面上的一个点。每个在海岸线上架设的雷达监测站,都只能覆盖以R 为半径的一个圆,所以海面上的小岛能被覆盖的条件是它距离海岸线上的雷达监测站的距离小于或者等于R。给定n个小岛以及这些小岛的位置,并输入雷达的辐射面积 R,问最少需要多少个雷达站才能覆盖所有小岛。
问题分析: 可以将问题转化为求区间选择问题的最大不冲突区间数,而后用贪心法求解。以每个小岛为圆心,R为半径画圆,圆在x 轴下方的部分即为可以覆盖该小岛的雷达架设区域,易知其 他条件不变时雷达架在海岸线比内陆能覆盖更广的区域,因此只需要考虑海岸线上的点。如图 1 所示, 以每个小岛为圆心的圆都与海岸线的相交所得到的弦即为我们可以架设雷达的区间,设小岛 T 的坐标 为(x,y),如果 y>R,那么这个问题无解,无论在哪里建站都覆盖不到这个小岛。如果 y<=R,那么区间 的起始时间为:x-sqrt(R*R-y*y) ,结束时间为:x+sqrt(R*R+y*y) ,按照结束时间对区间进行排序,在考察每个区间的时候,需要判断该区间的起始时间是否在上一区间的结束时间之前,本问题已完全转化为区间选择问题。下图中Ti表示海上的小岛。
代码
#include<iostream>
#include<algorithm>
#include<queue>
#include<functional>
using namespace std;
int n, num, counter = 0;
double d, x[1010], y[1010], a[1010], b[1010], temp1[1010], temp2[1010], temp;
bool panbie;

void merge(int begin, int mid, int end)
{
	int i = begin;
	int j = mid + 1;
	int k = begin;

	while (i <= mid && j <= end)
	{
		if (b[i]>b[j])
		{
			temp1[k] = a[j];
			temp2[k] = b[j];
			k++;
			j++;
		}
		else
		{
			temp1[k] = a[i];
			temp2[k] = b[i];
			k++;
			i++;
		}
	}
	while (i <= mid)
	{
		temp1[k] = a[i];
		temp2[k] = b[i];
		k++;
		i++;
	}
	while (j <= end)
	{
		temp1[k] = a[j];
		temp2[k] = b[j];
		k++;
		j++;
	}

	for (int p = begin; p <= end; p++)
	{
		a[p] = temp1[p];
		b[p] = temp2[p];
	}
}

void mergesort(int begin, int end)
{
	if (begin >= end)
		return;

	int mid = (begin + end) / 2;
	mergesort(begin, mid);
	mergesort(mid + 1, end);
	merge(begin, mid, end);
}

int main()
{
	while (1)
	{
		panbie = true;
		cin >> n >> d;
		if (n == 0 && d == 0)
			break;
		for (int i = 0; i<n; i++)
		{
			cin >> x[i] >> y[i];
			if (y[i]>d)
				panbie = false;
		}

		for (int i = 0; i<n; i++)
		{
			a[i] = x[i] - sqrt(d*d - y[i] * y[i]);
			b[i] = x[i] + sqrt(d*d - y[i] * y[i]);
		}

		mergesort(0, n - 1);
		num = 1;
		temp = b[0];

		for (int i = 1; i<n; i++)
		{
			if (a[i]>temp)
			{
				num++;
				temp = b[i];
			}
		}

		counter++;
		if (panbie == true)
			cout << "Case " << counter << ": " << num << endl;
		else
			cout << "Case " << counter << ": " << "-1" << endl;
	}
	system("pause");
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值