zoukankan      html  css  js  c++  java
  • 题解【AcWing1089】烽火传递

    题面

    单调队列优化 DP 模板题。

    我们考虑设 (dp_{i}) 表示从 (1)(i) 能够准确传递情报,且第 (i) 个烽火台发出信号的最小费用。

    转移方程不难得出:(dp_{i} = min_{i-m leq j leq i-1}{dp_j} + a_i)(a_i) 为第 (i) 个烽火台发出信号的费用)。

    看到转移的条件:(i-m leq j leq i - 1),这其实就是一个滑动窗口问题。

    用一个单调队列维护长度为 (m) 的滑动窗口即可。

    最后的答案是 (min_{n-m-1leq i leq n}{dp_i})

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 200003;
    
    int n, m, a[N], q[N], hh, tt, ans, dp[N];
    
    int main()
    {
        cin >> n >> m;
        for (int i = 1; i <= n; i+=1) cin >> a[i];
        hh = 0, tt = 0; //注意一开始队列中是有元素的
        for (int i = 1; i <= n; i+=1) //对于每一个烽火台进行转移
        {
            while (hh <= tt && q[hh] < i - m) ++hh; //队头是否在区间内
            dp[i] = dp[q[hh]] + a[i]; //DP 值转移
            while (hh <= tt && dp[q[tt]] >= dp[i]) --tt; //维护队列单调性
            q[++tt] = i; //加入队列
        }
        ans = 2000000007; //答案
        for (int i = n - m + 1; i <= n; i+=1) 
            ans = min(ans, dp[i]); //答案要从 n - m + 1 ~ n 的 DP 值中取最小值
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    RecyclerView+CardView简单使用
    Android六大进程间通信方式总结之一:基本知识
    前台服务
    Notification
    SQLite的基本用法
    SharePreferences基本用法
    自定义控件和使用的两种基本方法
    AsyncTask的简单使用
    Java Servlet调用数据库复习
    JDBC数据源(DataSource)的简单实现
  • 原文地址:https://www.cnblogs.com/xsl19/p/12362080.html
Copyright © 2011-2022 走看看