NOIP2010初賽 烽火傳遞

2021-09-30 13:23:16 字數 3957 閱讀 4561

烽火台又稱烽燧,是重要的軍事防禦設施,一般建在險要或交通要道上。一旦有敵情發生,白天燃燒柴草,通過濃煙表達資訊;夜晚燃燒乾柴,以火光傳遞軍情,在某兩座城市之間有

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 的罪犯被關押在同一監...