• 一本通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
  • 相关阅读:
    Android笔记:数据储存
    Android笔记:管理所有活动
    Android随笔:属性
    Android笔记:限定符
    Android笔记:ninepatch
    Android笔记:获取屏幕信息
    js自动完成
    动态生成实体类
    EF框架学习手记
    js遮罩效果
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10372074.html
Copyright © 2020-2023  润新知