题目描述
烽火台是重要的军事防御设施,一般建在交通要道或险要处。
一旦有军情发生,则白天用浓烟,晚上有火光传递军情。
在某两个城市之间有 座烽火台,每个烽火台发出信号都有一定的代价。
为了使情报准确传递,在连续 个烽火台中至少要有一个发出信号。
现在输入 和每个烽火台的代价,请计算在两城市之间准确传递情报所需花费的总代价最少为多少。
输入格式
第一行是两个整数 具体含义见题目描述;
第二行 个整数表示每个烽火台的代价 。
输出格式
输出仅一个整数,表示最小代价。
数据范围
,
输入样例:
5 3
1 2 5 6 2
输出样例:
4
题目分析
这是一道 单调队列优化DP 的题目。
首先对于烽火台 ,我们知道在烽火台 中至少要有一个烽火台投入使用,经过在此分析后,可知有且只有一个投入使用,若多于一个则中间的烽火台可以排除不用。
于是,我们定义 表示在烽火台 使用的条件下,烽火从起点城市传递到烽火台 的最小代价。这时我们可以将起末城市看作代价为 的烽火台。对于每个烽火台,我们需要维护 中的最小值。
通过前期的学习,我们可以利用单调队列维护定长区间最小值的方式来进行解答,每次烽火台 的状态转移只需要取队头下标所代表的烽火台 进行转移。
最终答案为 。
Accept代码
#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
int n, m;
int h[N], f[N], q[N];
int hh, tt;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i ++) cin >> h[i];
for (int i = 1; i <= n + 1; i ++)
{
if (q[hh] < i - m) hh ++;
f[i] = f[q[hh]] + h[i];
while (hh <= tt && f[q[tt]] >= f[i]) tt --;
q[++ tt] = i;
}
cout << f[n + 1] << "\n";
return 0;
}