4421 信号(贪心)

1. 问题描述:

有 n 个房子排成一排,从左到右依次编号为 1∼n,其中一些房子内装有无线信号发射器,这些信号发射器的有效覆盖半径为 r,更准确地说,如果第 p 号房子内装有信号发射器,则所有房间编号在 [p − r + 1,p + r − 1] 范围内的房子均可被其发出的无线信号覆盖,而其余房子则不会被其发出的无线信号覆盖。例如,假设 n = 6,r = 2,且第 2、5 号房子内装有信号发射器,则第 2 号房子内的发射器发出的信号可以覆盖第 1∼3 号房子,第 5 号房子内的发射器发出的信号可以覆盖第 4∼6 号房子,将两个发射器全部打开,则无线信号可以覆盖到所有房子,初始时所有无线信号发射器都是关闭的,请计算至少开启多少个无线信号发射器,才能保证所有房子都被无线信号覆盖到。

输入格式

第一行包含两个整数 n 和 r,第二行包含 n 个整数 a1,a2,…,an,每个数要么是 1,要么是 0,ai = 1 表示第 i 号房子内装有无线信号发射器,ai = 0 表示第 i 号房子内未装无线信号发射器。

输出格式

一个整数,表示需要开启的无线信号发射器的最少数量。如果无法使得所有房子都被无线信号覆盖到,则输出 −1

数据范围

前 6 个测试点满足 1 ≤ n ≤ 10
所有测试点满足 1 ≤ n,r ≤ 1000,0 ≤ ai ≤ 1

输入样例1:

6 2
0 1 1 0 0 1

输出样例1:

3

输入样例2:

5 3
1 0 0 0 1

输出样例2:

2

输入样例3:

5 10
0 0 0 0 0

输出样例3:

-1

输入样例4:

10 3
0 0 1 1 0 1 0 0 0 1

输出样例4:
3
来源:https://www.acwing.com/problem/content/description/4424/

2. 思路分析:

分析题目可以知道如果当前房子能够被两个发射器覆盖,那么我们应该选择距离当前房子较远的那个放射器,这样较远的发射器右边可以覆盖更远的范围,基于这个想法我们可以使用一个变量 last 来存储上一个发射器覆盖的最远范围,对于当前枚举的发射器 q[i] 如果左边覆盖的范围大于 last 说明至少存在 last 的下一个位置不能够被最近的发射器 q[i] 覆盖那么直接 break,说明最近的发射器都不满足条件说明后面的发射器就更不满足条件了,如果当前的发射器能够覆盖 last 后面的范围那么找到能够覆盖 last 后面范围的最远发射器 q[j],此时这个发射器右边能够覆盖的范围肯定是最大的,更新 last = q[j] + r - 1 ,所需要的的发射器数目加1,最终判断覆盖的距离是否大于等于 n,如果大于等于 n 说明满足题目的要求:

3. 代码如下:

python:

class Solution:
    def process(self):
        n, r = map(int, input().split())
        a = list(map(int, input().split()))
        # q记录发射器的位置
        q = list()
        for i in range(1, n + 1):
            if a[i - 1]:
                q.append(i)
        last = res = 0
        i = 0
        while i < len(q):
            # 当last>=n的时候说明全部房间已经覆盖
            if last >= n: break
            # 说明最近的发射器都无法覆盖last的下一个位置直接break
            if q[i] - r > last:
                break
            j = i
            # 求解能够覆盖当前last位置最远的发射器
            while j + 1 < len(q) and q[j + 1] - r <= last: j += 1
            res += 1
            # 更新一下能够当前发射器能够覆盖的最远距离
            last = q[j] + r - 1
            # 进入下一个发射器
            i = j + 1
        # 判断最终覆盖的距离是否小于n, 小于n则无解
        if last < n: res = -1
        print(res)


if __name__ == '__main__':
    Solution().process()

go:

package main

import "fmt"

func main() {
	var n, r, x int
	fmt.Scan(&n, &r)
	var q []int
    // 注意下标是从1开始的
	for i := 1; i <= n; i++ {
		fmt.Scan(&x)
		if x > 0 {
			q = append(q, i)
		}
	}
	last := 0
	res := 0
	for i := 0; i < len(q); i++ {
		if last >= n {
			break
		}
		if q[i]-r > last {
			break
		}
		j := i
		for j+1 < len(q) && q[j+1]-r <= last {
			j += 1
		}
		last = q[j] + r - 1
		res += 1
		i = j
	}
	if last < n {
		res = -1
	}
	fmt.Println(res)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值