JDOJ-1056: 烽火传递
Posted oi-forever
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDOJ-1056: 烽火传递相关的知识,希望对你有一定的参考价值。
1056: 烽火传递
Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 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: 烽火传递的主要内容,如果未能解决你的问题,请参考以下文章