【Jzoj1771】烽火传递 单调队列优化dp

题目链接

http://swordoj.win/problem/577

题目

烽火台又称烽燧,是重要的军事防御设施,一般建在险要或交通要道上。一旦有敌情发生,白天燃烧柴草,定代价。
为了使情报准确地传递,在连续m个烽火台中至少要有一个发出信号。请计算总共最少花费多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确传递。
【输入格式】
 第一行:两个整数N,M。其中N表示烽火台的个数,M表示在连续m个烽火台中至少要有一个发出信号。
接下来N行,每行一个数Wi,表示第i个烽火台发出信号所需代价。
【输出格式】
一行,表示答案。
【输入样例1】
5 3
1
2
5
6
2
【输出样例1】
4
【数据范围】
对于50%的数据,M≤N≤1,000。
对于100%的数据,M≤N≤ 100,000,Wi≤100。

解题

设dp[i]表示前i个烽火台且第i个烽火台点火的最少代价。
那么,dp[i]=dp[i-j]+a[i],1<=j<=m.
看数据范围,摆明了要你用单调队列优化。
常规操作一波即可。

代码

没有权限,交不了,但样例过了,哈哈哈= =不管了。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3
using namespace std;

const int maxn=1e5+7;
int que[maxn],a[maxn];
int N,M;
int dp[maxn];

int main()
{
    while(~scanf("%d%d",&N,&M))
    {
        for(int i=1;i<=N;i++)
            scanf("%d",&a[i]);
        memset(dp,0,sizeof(dp));
        int L=1,R=0;
        que[++R]=0;
        for(int i=1;i<=N;i++)
        {
            while(L<=R && que[L]<i-M) L++;
            dp[i]=dp[que[L]]+a[i];
            //cout<<"dp["<<i<<"]="<<dp[i]<<endl;
            while(L<=R && dp[que[R]]>=dp[i]) R--;
            que[++R]=i;
        }
        int ans=INF;
        for(int i=N;i>=N-M+1;i--)
            ans=min(ans,dp[i]);
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37685156/article/details/81434451
今日推荐