JDOJ-1056: 烽火传递

Posted oi-forever

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDOJ-1056: 烽火传递相关的知识,希望对你有一定的参考价值。

1056: 烽火传递

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 209  Solved: 87
[Submit][Status][Web Board]

Description

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

Input

  第一行:两个整数N,M。其中N表示烽火台的个数,M表示在连续m个烽火台中至少要有一个发出信号。接下来N行,每行一个数Wi,表示第i个烽火台发出信号所需代价。

Output

  一行,表示答案。

Sample Input

5 3 1 2 5 6 2

Sample Output

4

HINT

 

【数据范围】  对于50%的数据,M≤N≤1,000 。  对于100%的数据,M≤N≤ 100,000,Wi≤100。

总结:单调队列优化dp模板
容易想到方程dp[i] = min(dp[j]) (i - m <= j <= i - 1)
然后就单调队列优化
#include<bits/stdc++.h>

using namespace std;
const int maxn = 400005;
#define inf 10000007

int head = 1, n, m, wi[maxn], q[maxn], tail = 1, num[maxn];
long long dp[maxn];
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) scanf("%d", &wi[i]);
	for (int i = 1; i <= n; ++i) dp[i] = -inf;
	for (int i = 1; i <= n; ++i) {
		dp[i] = dp[num[head]] + wi[i];
		while(head <= tail && dp[i] <= dp[num[tail]]) tail--;
		num[++tail] = i;
		while(num[head] < i + 1 - m)  head++;
	} printf("%lld\n", dp[num[head]]);
	return 0;
}

  

以上是关于JDOJ-1056: 烽火传递的主要内容,如果未能解决你的问题,请参考以下文章

烽火传递dp + 单调队列优化

[TyvjP1313] [NOIP2010初赛]烽火传递(单调队列 + DP)

烽火传递 NOIP2010初赛 单调队列优化

单调队列优化DP烽火传递 LibreOJ - 10180

Acwing 1089. 烽火传递

SSL_2883烽火传递