烽火传递
Description
烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上。一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情。在某两座城市之间有n个烽火台,每个烽火台发出信号都有一定的代价。为了使情报准确的传递,在m个烽火台中至少要有一个发出信号。现输入n、m和每个烽火台发出的信号的代价,请计算总共最少需要话费多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确的传递!!!
Input Format
第一行有两个数n,m分别表示n个烽火台,在m个烽火台中至少要有一个发出信号。
第二行为n个数,表示每一个烽火台的代价。
Output Format
一个数,即最小代价。
样例
5 3
1 2 5 6 2
4
时间限制 Time Limitation
各个测试点1s
注释 Hint
1<=n,m<=1,000,000
表示被这题坑了快3个多小时了,主要还是DP没学好啊,最后一个for循环很巧妙,之前想了好久都没想到这点,还用了两个单调队列。。。悲剧阿。。。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX ((1<<31)-1)
using namespace std;
int value[1000010],Q[1000010],dp[1000010]={0};
int main()
{
int ans=MAX;
int i,n,m,front=0,rear=0;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d",&value[i]);
while(front<=rear&&(dp[Q[rear-1]]>dp[i-1]))
rear--;
Q[rear++] = i-1;
while(front<rear&&(i-Q[front])>m)
front++;
dp[i]=dp[Q[front]]+value[i];
}
// for(i=1;i<=n;i++)
// printf("%d\n",dp[i]);
for(i=n;i>=n-m+1;i--)
{
if(ans>dp[i])
ans = dp[i];
}
printf("%d\n",ans);
return 0;
}