烽火传递
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。
题目分析
由题可列出方程:
F
[
i
]
=
m
i
n
(
F
[
j
]
)
+
a
[
i
]
(
i
−
m
<
j
<
i
)
F[i]=min(F[j])+a[i](i−m<j<i)
F[i]=min(F[j])+a[i](i−m<j<i)
方程中的
m
i
n
min
min部分我们要用单调队列来实现
代码
#include<iostream>
#include<deque>
#include<cstdio>
#include<algorithm>
#include<iomanip>
using namespace std;
long long n,m,a[100005],f[100005],x,big=2147483647;
deque<int> b;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
while(b.size()!=0&&f[b.back()]>=f[i-1]) b.pop_back();//保持单调
b.push_back(i-1);//从队尾入队
while(b.size()!=0&&b.front()<i-m) b.pop_front();
f[i]=f[b.front()]+a[i];
if(i>=n-m+1) big=min(big,f[i]);//方程
}
cout<<big;
return 0;
}