烽火台又稱烽燧,是重要的軍事防禦設施,一般建在險要或交通要道上。一旦有敵情發生,白天燃燒柴草,通過濃煙表達資訊;夜晚燃燒乾柴,以火光傳遞軍情,在某兩座城市之間有
n n
個烽火台,每個烽火台發出訊號都有一定代價。為了使情報準確地傳遞,在連續
m m
個烽火台中至少要有乙個發出訊號。請計算總共最少花費多少代價,才能使敵軍來襲之時,情報能在這兩座城市之間準確傳遞。
第一行:兩個整數n,
m n,m
。其中n表示烽火台的個數,
m m
表示在連續
m m
個烽火台中至少要有乙個發出訊號。接下來
n n
行,每行乙個數wi
w
i,表示第i個烽火台發出訊號所需代價。
一行,表示答案。
5 3
1 2
5 6
2對於50%的資料,m≤
n≤1,
000 m≤n
≤1
,000
。 對於100%的資料,m≤
n≤100,
000,wi
≤100
m ≤n
≤100
,000,w
i≤
100。
很明顯,對於第
i i
個烽火台有兩種狀態——點燃與不點燃。
因此我們設fi
,0f i,
0和fi
,1f i,
1,fi
,0f i,
0表示前
i i
個烽火台如果第
i i
個不點燃需要付出的最小代價,fi
,1f i,
1則表示點燃第
i i
個的最小代價。
如果第i個烽火台不點燃,那麼在
i i
之前的m−
1' role="presentation" style="position: relative;">m−1
m−1個烽火台必須至少有乙個要點燃的,也就是說,fi
,0=m
in(f
i−k,
1),k
∈[1,
m−1]
f i,
0=mi
n(fi
−k,1
),k∈
[1,m
−1]。
如果點燃,當前最小代價就是前
m m
個的最小值加第
i' role="presentation" style="position: relative;">i
i個的代價,即 fi
,1=m
in(f
i−k,
1+ci
),k∈
[1,m
] fi,
1=mi
n(fi
−k,1
+ci)
,k∈[
1,m]
注意這裡包括第
m m
個。 但是有個問題。
如果每次都列舉,那麼複雜度則變為n2
n
2,不超時才怪。
所以,這裡就是單調佇列的登場\(^o^)/
單調佇列,簡單地說,就是能快速尋找某點前的最大/最小值的玩意兒。
對於這題來講,當然是維護使dt
12<..
.i dt1
2<..
.
i就可解決問題了。
進隊時,將進隊的元素為
e e
,從隊尾往前掃瞄,直到找到乙個不大於
e e
的元素d d
,將e e
放在d d
之後,捨棄
e e
之後的所有元素;如果沒有找到這樣乙個
d d
,則將e e
放在隊頭(此時佇列裡只有這乙個元素)。
出隊時,將出隊的元素為
e e
,從隊頭向後掃瞄,直到找到乙個元素
f f
比e e
後進隊,捨棄
f f
之前所有的。(實際操作中,由於是按序逐個出隊,所以每次只需要出隊只需要比較隊頭)。
附:此篇為筆者人生第一篇部落格,內容和排版這些細節先不必在意啦。
var n,m,i,j,head,tail,j2:longint;
a:array[1..100000] of longint;
k:array[1..100000,1..2] of longint;
f:array[1..100000,0..1] of longint;
p:boolean;
function
min(x,y:longint):longint;
begin
if xthen
exit(x) else
exit(y);
end;
begin
readln(n,m);
// for i:=1 to n do f[i,0]:=maxlongint;
for i:=1
to n do readln(a[i]);
f[1,1]:=a[1];
f[2,0]:=a[1];
f[2,1]:=a[2];
k[1,1]:=a[1];
k[1,2]:=1;
tail:=1;
head:=1;
for i:=3
to m do
begin
f[i,1]:=a[i];
p:=true;
for j:=tail downto head do
if k[j,1]<=f[i-1,1] then
begin
p:=false;
k[j+1,1]:=f[i-1,1];
k[j+1,2]:=i-1;
tail:=j+1;
break;
end;
if p then
begin
k[head,1]:=f[i-1,1];
k[head,2]:=i-1;
tail:=head;
end;
f[i,0]:=k[head,1];
end;
for i:=m+1
to n do
begin
p:=true;
for j:=tail downto head do
if k[j,1]<=f[i-1,1] then
begin
p:=false;
k[j+1,1]:=f[i-1,1];
k[j+1,2]:=i-1;
tail:=j+1;
break;
end;
if p then
begin
k[head,1]:=f[i-1,1];
k[head,2]:=i-1;
tail:=head;
end;
f[i,1]:=k[head,1]+a[i];
for j:=head to tail do
begin
if k[head,2]=i-m then
begin
for j2:=head to tail do
if k[j2,2]>k[head,2] then
begin
head:=j2;
break;
end;
end;
end;
f[i,0]:=k[head,1];
end;
writeln(min(f[n,1],f[n,0]));
end.
NOIP2010初賽 烽火傳遞 單調佇列詳細整理
p1313烽火台又稱烽燧,是重要的防禦設施,一般建在險要處或交通要道上。一旦有敵情發生,白天燃燒柴草,通過濃煙表達資訊 夜晚燃燒乾柴,以火光傳遞軍情。在某兩座城市之間有n個烽火台,每個烽火台發出訊號都有一定的代價。為了使情報準確的傳遞,在m個烽火台中至少要有乙個發出訊號。現輸入n m和每個烽火台發出...
NOIP2010普及組初賽試題錯題整理
11 乙個字長為8位的整數的補碼是11111001,則它的原碼是 d a.00000111 b.01111001 c.11111001 d.10000111 分析 二進位制中負數才有補碼,將補碼 1再按位取反,注意第一位保留1.佇列快照是指在某一時刻佇列中的元素組成的有序序列。例如,當元素1 2 3...
noip2010 關押罪犯
s 城現有兩座監獄,一共關押著n 名罪犯,編號分別為1 n。他們之間的關係自然也極 不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發衝突。我們用 怨 氣值 乙個正整數值 來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之 間的積怨越多。如果兩名怨氣值為c 的罪犯被關押在同一監...