【tyvj1313】烽火传递

245 篇文章 0 订阅
9 篇文章 0 订阅

描述

  烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上。一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情。在某两座城市之间有n个烽火台,每个烽火台发出信号都有一定的代价。为了使情报准确的传递,在m个烽火台中至少要有一个发出信号。现输入n、m和每个烽火台发出的信号的代价,请计算总共最少需要话费多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确的传递!!!

输入格式

第一行有两个数n,m分别表示n个烽火台,在m个烽火台中至少要有一个发出信号。
第二行为n个数,表示每一个烽火台的代价。

输出格式

一个数,即最小代价。

测试样例1

输入

5 3 
1 2 5 6 2

输出

4

备注

1<=n,m<=1,000,000
【题解】

和修剪草坪那道题很像。也可以用单调队列来优化。

f[i]表示以i为结尾,i必选,所获得的最小代价。

那么f[i]就可以表示为前一个状态的最小值(必须在i前面的m个里)再加上当前的值(因为i必选),可以用单调队列来优化成O(n)

【代码】

#include<iostream>
#include<cstring>
#include<cstdio>
#define inf 2100000000 
using namespace std;
int n,m,head,tail,Min;
int queue[1000005],a[1000005],f[1000005];
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;++i) scanf("%d",&a[i]);
	for (int i=1;i<=n;++i){
		while (queue[head]<i-m&&head<=tail) head++;
		f[i]=a[i]+f[queue[head]];
		while (f[queue[tail]]>f[i]&&head<=tail) tail--;
		queue[++tail]=i;
	}
	Min=inf;
	for (int i=n-m+1;i<=n;++i)
	  Min=min(Min,f[i]);
	printf("%d\n",Min);
}

再说一下细节问题:

①先调整单调队列的范围,再更新当前的f

②可选与不可选的范围要注意

③状态的表示决定了最后需要枚举最小值,但是这个枚举必须从n-m+1开始,因为最后m个里必选一个


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值