zoukankan      html  css  js  c++  java
  • 【烽火传递】dp + 单调队列优化

    题目描述

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

    输入格式

    第一行有两个数 n,m 分别表示 n 个烽火台,在任意连续的 m 个烽火台中至少要有一个发出信号。
    第二行为 n 个数,表示每一个烽火台的代价。

    输出格式

    一个整数,即最小代价。

    样例数据 1

    输入

    5 3 
    1 2 5 6 2

    输出

    4

    备注

    【数据范围】

    1<=n,m<=1,000,000,保证答案在 int 范围内。
    1<=n,m<=1,000,000,保证答案在 int 范围内。

    题目分析

    首先考虑dp,因为每m个点中必须选择2个,那么对于当前点(i),$f[i] = min{f[j]}+ val[i] (i - m + 1 ≤ j < i )$

    这样的每次要去寻找最小值,复杂度报表,考虑dp优化。

    由于要取最小值,那么就可以维护一个单调递增的单调队列,每次入队维护单调性,并删除队首不在区间中的数,然后队首就是要找的最小值。

    这样下来,时间复杂度$o(n)$

    code

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    const int N = 1e6 + 5, oo = 0x3f3f3f3f;
    struct node{
        int val, id;
    };
    node que[N];
    int cost[N], head, tail, i, f[N];
    int n, m;
    
    inline int read(){
        int i = 0, f = 1; char ch = getchar();
        for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
        if(ch == '-') f = -1, ch = getchar();
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            i = (i << 3) + (i << 1) + (ch - '0');
        return i * f;
    }
    
    inline void wr(int x){
        if(x < 0) putchar('-'), x = -x;
        if(x > 9) wr(x / 10);
        putchar(x%10+'0');
    }
    
    int main(){
        n = read(), m = read();
        for(i = 1; i <= n; i++) cost[i] = read();
        head = 1, tail = 1;
        for(i = 1; i <= n; i++){
            while(que[head].id < i - m && head <= tail) head++;
            f[i] = que[head].val + cost[i];
            while(tail >= head && que[tail].val >= f[i]) tail--;
            que[++tail] = (node){f[i], i};
    //        for(int j = head; j <= tail; j++) cout<<que[j].val<<" ";cout<<endl;
        }
        int ans = oo;
        for(int i = n - m + 1; i <= n; i++)
            ans = min(ans, f[i]);
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    URLEncode解决url中有特殊字符的问题
    监控系统概览
    SpringBoot 上传文件夹
    关于postgresql报 ERROR: XXX does not exist
    postgresql学习
    git学习
    学习博客
    面试准备
    jvm
    线程池面试题
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7253499.html
Copyright © 2011-2022 走看看