현재 위치 - 법률 상담 무료 플랫폼 - 법률 자문 무료 플랫폼 - NOIP2005改進組復賽第二題詳細解答
NOIP2005改進組復賽第二題詳細解答
初步分析:

設f(i)代表至少到達坐標I時踩過的石頭數。

R(i)表示坐標I上是否有石頭,如果有石頭,r(i)=1,否則r(i)=0。

F(i)=min{f(j)}+r(i),其中s

邊界f(0)=0

Ans=min{f(i)},其中I >;=L

該算法的時間復雜度為O(L*(t-s))。

深度分析:

直觀來說,我們沒有必要對壹個沒有石頭的大區域進行動態規劃。

可以證明,當空白區域大於某個max時,青蛙壹定可以從區域的壹端跳到另壹端。

事實上,對於跳躍間隔[s,t],max

所以我們可以把每段的長度>:max的空白區域壓縮到max的長度。這樣,總的L '只有m * max

這樣,前面的動態規劃的復雜度為O(L'*(t-s)),在限定的時間內可以得到解。

這個分析是NOIP2005唯壹獲獎者(保送北大)姚金玉給出的:長沙雅禮中學。

【問題分析】

乍壹看,這個問題是壹個典型的搜索問題。從河的壹邊到另壹邊,找到可以踩的最少的石頭。但是從數據範圍來看。1 ...109橋長。即使是O(n)算法也無法在壹秒鐘內解出答案。

如果搜索石頭,方法就比較難了。這個要考慮到前後連續的石頭。換壹種方式。利用動態規劃,具有分階段石頭的壹維動態量規的時間復雜度為O(n2)。最多只有100×100的時間。但是這樣劃分狀態是很復雜的。因為結石的分布是沒有規律的,而且有後遺癥。

所以我們必須回去搜索。尋找石頭會像移動的規則壹樣不規則。我們搜索壹座橋的長度,然後加上壹個巧妙的剪枝,在很短的時間內求解。可以稱之為O(m2)。【註:所謂這個詞已經成為湖南OI本世紀的流行詞】

【話題實現】

先搜索時間。時間復雜度為O(L)。從橋的壹邊到另壹邊,中間最多只有100塊石頭。假設橋長最大(109),石頭數也最大(100)。這樣的話,中間肯定有很多“空條”(兩塊石頭裏的空白)。如果在處理時跳過這些,就只有m個操作。關鍵是找出每壹個可以跳過的“空條”。

我們可以先找出青蛙能跳出的所有可能性,再找出可以忽略的“空條”。

[特殊算法]

A[i]:第壹個I坐標的最小石子數,初始數是I坐標的石子數。

B[i]:第I塊石頭的坐標。

移動量規

a[0]= 0;

右n & gt=t

a[n]=min{a[n]+a[n-s],a[n]+a[n-s-1],...,a[n]+a[n-t]}

右側s =

a[n]=max{a[n]+a[n-s],a[n]+a[n-s-1],...,a[n]+a[0]}

但是,由於n較大,直接作用量規會超時。所以n要壓縮。

看坐標可以發現,如果b[I]-b[I-1]>;t,顯然對於b [I-1]+t

註意,在計算過程中,因為有些坐標永遠無法到達,所以需要使用布爾數組c[n]進行判斷。方法是,對於c[n],如果0;s,c [n-t],c [n-t+1],...,c [n-s]都為假,那麽c[n]也為假。

程序:

var f:array [0..9]的longword

ts,stone:array [0..longint的100];

j,I,s,t,l:longint;

k,os:字節;

tmp:long word;

函數gbs(l,r:byte):long word;

var i:字節;

開始

GBS:= 1;

for I:= l to r do GBS:= GBS * I;

結束;

開始

賦值(輸入,' river . in ');

賦值(output,' river . out ');

復位(輸入);

重寫(輸出);

filldword(f,sizeof(f) div 4,maxlongint);

readln(l);

readln(s,t,stone[0]);

for I:= 1 to stone[0]do read(stone[I]);

對於i:=1 to stone[0] do

對於j:=1至i-1 do

如果stone[j]& gt;stone[i]然後開始tmp:= stone[I];stone[I]:= stone[j];stone[j]:= tmp;結束;

ts[0]:= stone[0];

ts[1]:= stone[1]mod(GBS(s,t));

如果ts[1]=0那麽ts[1]:= t;

對於i:=2到stone[0] do

開始

ts[I]:= ts[I-1]+(stone[I]-stone[I-1])mod(GBS(s,t));

if (ts[i]=ts[i-1])則ts[I]:= ts[I]+t;

if(stone[I]-stone[I-1]& lt;& gt1)且(ts[i]=ts[i-1]+1)則ts[I]:= ts[I]+t;

結束;

l:= ts[ts[0]]+(l-s-stone[stone[0]])mod s+t;

石頭:= ts

f[0]:= 0;

因為我願意

開始

OS:= 0;

for k:= 1 to stone[0]do if stone[k]= I然後開始OS:= 1;中斷結束;

tmp:= maxlongint;

for j:=i-t to i-s do

開始

如果j & lt0然後繼續;

如果j & gt然後我打破了;

如果tmp & gtf[j mod 10]+os然後tmp:= f[j mod 10]+OS;

結束;

f[I mod 10]:= tmp;

結束;

j:= maxlongint;

for I:= l-t to l do if j & gt;f[i mod 10]那麽j:= f[I mod 10];

writeln(j);

關閉(輸出);

結束。