zoukankan      html  css  js  c++  java
  • 一本通1602烽火传递

    1602:烽火传递

    时间限制: 1000 ms         内存限制: 524288 KB

    【题目描述】

    原题来自:NOIP 2010 提高组初赛 · 完善程序

    烽火台是重要的军事防御设施,一般建在交通要道或险要处。一旦有军情发生,则白天用浓烟,晚上有火光传递军情。

    在某两个城市之间有 n 座烽火台,每个烽火台发出信号都有一定的代价。为了使情报准确传递,在连续 m 个烽火台中至少要有一个发出信号。现在输入 n,m 和每个烽火台的代价,请计算总共最少的代价在两城市之间来准确传递情报。

    【输入】

    第一行是 n,m,表示 n 个烽火台和连续烽火台数 m;

    第二行 n 个整数表示每个烽火台的代价 ai 。

    【输出】

    输出仅一个整数,表示最小代价。

    【输入样例】

    5 3
    1 2 5 6 2

    【输出样例】

    4

    【提示】

    样例说明

    在第 2,5 号烽火台上发信号。

    数据范围与提示:

    对于全部数据,1n,m2×105,1ai1000

    sol:dp[i]表示强制选i这个位置时1~i的最小代价,dp[i]=min(dp[i-m]~dp[i-1])+ a[i]

    min(dp[i-m]~dp[i-1])可以方便的用单调队列优化,所以复杂度就变成O(n)了

    答案就是min(dp[n-m+1]~dp[n])

    #include <bits/stdc++.h>
    using namespace std;
    typedef int ll;
    inline ll read()
    {
        ll s=0;
        bool f=0;
        char ch=' ';
        while(!isdigit(ch))
        {
            f|=(ch=='-');
            ch=getchar();
        }
        while(isdigit(ch))
        {
            s=(s<<3)+(s<<1)+(ch^48);
            ch=getchar();
        }
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x<10)
        {
            putchar(x+'0');
            return;
        }
        write(x/10);
        putchar((x%10)+'0');
        return;
    }
    inline void writeln(ll x)
    {
        write(x);
        putchar('
    ');
        return;
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) writeln(x)
    const int N=200005,inf=0x3f3f3f3f;
    int n,m,a[N],dp[N];
    struct Record
    {
        int Shuz,Weiz;
    }Ddq[N];
    int main()
    {
        int i,Head=1,Tail=0;
        R(n); R(m);
        for(i=1;i<=n;i++) R(a[i]);
        memset(dp,63,sizeof dp);
        for(i=1;i<=m;i++)
        {
            while(Head<Tail&&Ddq[Head].Weiz<i-m) Head++;
            dp[i]=a[i];
            while(Head<=Tail&&Ddq[Tail].Shuz>dp[i]) Tail--;
            Ddq[++Tail]=(Record){dp[i],i};
        }
        for(i=m+1;i<=n;i++)
        {
            while(Head<Tail&&Ddq[Head].Weiz<i-m) Head++;
            dp[i]=Ddq[Head].Shuz+a[i];
            while(Head<=Tail&&Ddq[Tail].Shuz>dp[i]) Tail--;
            Ddq[++Tail]=(Record){dp[i],i};
        }
        int ans=inf;
        for(i=n-m+1;i<=n;i++)
        {
            ans=min(ans,dp[i]);
        }
        Wl(ans);
        return 0;
    }
    /*
    input
    5 3
    1 2 5 6 2
    output
    4
    */
    View Code
  • 相关阅读:
    Java对象的生命周期与作用域的讨论(转)
    [置顶] Oracle学习路线与方法
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10372074.html
Copyright © 2011-2022 走看看