zoukankan      html  css  js  c++  java
  • SSLOJ 2883 烽火传递

    题目

       

    Description

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

    Input

    第一行:两个整数 NM。其中N表示烽火台的个数, M 表示在连续 m 个烽火台中至少要有一个发出信号。接下来 N 行,每行一个数 Wi,表示第i个烽火台发出信号所需代价。

    Output

    一行,表示答案。

      5 3

      1 2 5 6 2

      4   

    Data Constraint

    对于50%的数据,M≤N≤1,000 。 对于100%的数据,

    M≤N≤100,000Wi≤100

    分析

        这道很明显,如果用DP做一定超时,所以我们用单调队列优化

        那该怎么优化法呢

        首先我们分析状态转移方程  f[j]=min(f[j],f[k]+a[i])

        如果做的是循环k 然后直接枚举.  o(n^2)

        显然这肯定超时

        所以我们就这样做:

        构造一个递增单调队列,所以最小的值一定在队头

        用单调队列来代表f里面的值的

        这样就可以省下k这个循环了

        但是最后的答案是在i=n-m  i<=n 里

    代码

     1 #include<iostream>
     2 #define N 100000
     3 using namespace std;
     4 int a[N+1];
     5 int f[N+1],que[N+1];
     6 int main ()
     7 {
     8     int n,m;
     9     cin>>n>>m;
    10     for (int i=1;i<=n;i++)
    11         cin>>a[i];
    12     int h=1,t=1;
    13     for (int i=1;i<=n;i++)
    14     {
    15         while (h<=t&&f[i-1]<=f[que[t]]) t--;   //如果当前插入的值比队尾小就要插队
    16         que[++t]=i-1;
    17         while (h<=t&&que[h]+m<i) h++;  //如果超出范围就要头指针后移
    18         f[i]=f[que[h]]+a[i];   //结果就是当前队列最小值加上当前a了
    19     }
    20     int ans=1e9;
    21     for (int i=n;i>n-m;i--)
    22        ans=min(ans,f[i]);
    23     cout<<ans;
    24 }
    为何要逼自己长大,去闯不该闯的荒唐
  • 相关阅读:
    《痕迹识人,面试读心》培训总结之一
    傲游与视频网站广告之战的思考
    EMLS项目推进思考
    二级证丢失如何找回
    Mathematica 讲座
    泊松方程解法
    Windows核心编程-作业
    Win7多用户同时登陆
    C语言文件操作类型速查
    openMP的一点使用经验
  • 原文地址:https://www.cnblogs.com/zjzjzj/p/10225058.html
Copyright © 2011-2022 走看看