问题描述
在一条街上有 n 所房子, H[i] (1 ≤ i ≤ n) 是第 i 所房子离街道起点处的距离 (以米为单位),假定 H[1] < H[2] < · · · < H[n]。目前该街道上还没有一所邮局,现计划新建若干所邮局,使得每所房子到最近的邮局距离在 100 米以内。试设计一个时间复杂度为 O(n) 的算法,计算出新建邮局的位置,即每所新建邮局离街道起点处的距离 P [j] (1 ≤ j ≤ m),同时确保新建邮局个数 m 最小。
分析
为了使邮局数量m最小,也就是说我们要让邮局的存在效用最大化,即每个邮局的覆盖范围最大话,如何做才能让单个邮局覆盖范围最大呢?当然是把邮局建在两栋房子之间。下面用一个图来说明(画得有点挫,见谅!!!):
从图里面可以看出,Post[1]设立在H[1]+100处时覆盖范围最广(Post[i]表示第i所邮局,1 ≤ i ≤ n),在此点的右边设立,不符合题意,第一户人家距离邮局太远,若在左边,那么范围不够大,导致邮局数量变多,也不符合贪心策略思想。将第一个邮局设立之后,应当考虑Post[2],Post[3]…。假如H[2]到Post[1]的距离在100m以内(包括100m),那么Post[1]可以覆盖H[1]和H[2],现在只需要考虑为H[3]以后的房子建邮局,即在H[3]+100处新建邮局;反之,如果H[2]到Post[1]的距离在100m之外,那么,Post[1]的覆盖范围只是H[1],我们需要为H[2]及其后的房子新建邮局,即在H[2]+100处新建。后面依次类推。
将上述分析一般化。
Post[i]为在H[i]+100处新建的邮局,如果H[i+1] - Post[i] ≤ 100 ,那么,下一个邮局在H[i+2]+100处新建;如果H[i+1] - Post[i] >100,那么,下一个邮局在H[i+1]+100处新建。据此,可以写出下面的算法。
- Note:将起点start当做H[0]和Post[0]
代码实现
- C语言实现
#include <stdio.h>
#include <stdlib.h>
#define BASE 100 //每所房子到最近的邮局距离
#define N 4 //房子数量
int greedy_algorithm(int h[],int post[],int n)
{
int i = 1;
int num = 0;
while(i <= n)
{
post[++num] = h[i] + BASE;
if