烽火传递
【题目描述】
烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上。一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情。在某两座城市之间有n个烽火台,每个烽火台发出信号都有一定的代价。为了使情报准确的传递,在m个烽火台中至少要有一个发出信号。现输入n、m和每个烽火台发出的信号的代价,请计算总共最少需要花费多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确的传递!!!
【输入描述】
第一行有两个数n,m(1<=n,m<=1000000)分别表示n个烽火台,在m个烽火台中至少要有一个发出信号。
第二行为n个数,表示每一个烽火台的代价。
【输出描述】
一个数,即最小代价。
【样例输入】
5 3
1 2 5 6 2
【样例输出】
4

分析:

多增加两个点表示两座城市,将它们看做代价为0的烽火台,然后很容易得到这个式子:

f[i]:=min(f[j])+a[i](i-m<=j<i)

然后用单调队列优化,队列元素保存f数组的值,维护单调递增队列,每次取队头即可。

代码1(DP+单调队列):

program fire;
var
  f,a,b,g:array[0..1000001]of longint;
  n,i,m,h,t:longint;
procedure work(x:longint);
begin
  t:=t+1; b[t]:=f[x]; g[t]:=x;
  while (b[t]<=b[t-1])and(t>h) do
    begin
      t:=t-1; b[t]:=b[t+1]; g[t]:=g[t+1];
    end;
  if x-g[h]=m then h:=h+1;
end;
begin
  assign(input,'fire.in');
reset(input);
assign(output,'fire.out');
rewrite(output);
  readln(n,m);
  for i:=1 to n do
   read(a[i]);
  n:=n+1;
  f[0]:=0; b[1]:=0;g[1]:=0;h:=1; t:=1;
  for i:=1 to n do
   begin
     f[i]:=b[h]+a[i];
     work(i);
   end;
  writeln(f[n]);
  close(input); close(output);
end.
View Code

相关文章:

  • 2021-09-24
  • 2022-12-23
  • 2022-02-05
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-21
  • 2021-11-12
猜你喜欢
  • 2022-12-23
  • 2021-08-23
  • 2022-03-01
  • 2022-12-23
  • 2022-12-23
  • 2021-12-18
相关资源
相似解决方案