練習 7 新飛行棋(BFS)

2021-10-18 21:42:44 字數 2587 閱讀 2871

description

期末考試終於結束了。andy同學感覺松了一口氣,他決定重溫小時候的快樂時光–下飛行棋。但是他弄丟了傳統飛行棋需要的骰子,因此他發明了一種新型的飛行棋遊戲,規則如下:棋盤上有n個格仔,由近到遠分別編號為1到n。對於1≤i≤n,第i個格仔上寫著乙個正整數ni。當玩家處於第a個格仔時,他可以選擇往後走na步,或者往前倒退na步。當然如果na+a>n,那麼他就只能選擇後退;同理如果a−na<1,那麼他就只能選擇前進。保證不會出現既不能前進又不能後退的格仔。

input

第一行三個整數,分別為n,s,t意義如題面所述。

第二行n個正整數,第i個數為ni。

output

乙個數,為最少經過的把數。如果s無法到達t,輸出-1。

samples

input

6 6 4

1 2 2 3 1 2

output

1hint

對於前10%的資料,s=t;

對於前40%的資料,n≤200;

對於另外10%的資料,s無法到達t;

對於100%的資料,n≤200000;

source

石光中學 fcs2018基礎班day 6

#include

using

namespace std;

typedef

long

long ll;

const

int n =

200005

;int n,s,t;

int a[n]

,cnt[n]

,k[n]

,u,v;

void

bfs()if

(v>=1&&

!k[v])}

}int

main()

bfs();

cout<

;return0;

}

這個是宇巨教的……

大題思路:

乙個陣列cnt來記錄到達該位置時,已經走的步數。這個陣列最初的時候初始化為-1,因為如果沒有答案的話(無法到達)可以直接輸出-1,(不能判斷cnt是否為0,因為0是有意義的,當起始位置就是終點的時候cnt可以為0)

乙個陣列k來標記是否走過這個位置(因為同乙個位置不可以走兩次)

然後我們看函式主體:

這裡是用到了fifo佇列queueq; q.push(s);k[s]=1;cnt[s]=0;我們把起始位置s壓入佇列,然後標記k[s]=1,表示這裡已經走過了不能再來了,並且cnt[s]=0,表示這裡是起始位置。

while

(q.size()

)if(v>=1&&

!k[v]

)}

很顯然這樣的話只要佇列裡有數就會不斷地測試,就會測試到每個可以到達的點

①這裡的u很顯然就是向前走的操作(x+a[x]),而v就是向後走的操作(x-a[x])。

②如果向前走在[1,n]範圍內,並且之前沒有到達過,就把這個點壓入佇列,並且步數+1。同樣,如果向後走在[1,n]範圍內,並且之前沒有到達過,就把這個點壓入佇列,並且步數+1。

那麼為什麼要判定是否走過這個點?

因為如果先前已經走過了那麼接下來的操作一定是重合的,並且先到達的在時間上一定是優先的。

可以參考上面的圖:

上面的過程需要3步才能到達4,而下面的過程只需要2步就能到達4,並且到達4以後的路徑不會因為選擇了上面或是下面的過程而改變。因此,先到達的在時間上一定是優先的。

我們這樣進行操作,最終一定是每次測試同一時間點到達的數

例如:我們最初的起始點是1,如果之後的操作我們可以向前也可以向後,那麼就會壓入兩個數值,實際上這兩個數值的先後順序並不重要,因為他們都是屬於第2層(cnt = 1)我們把第二層的點都測試完了之後,才會去測試第3層的數(cnt = 2)。

模擬一下佇列如下圖:

最初只有第1層,第1層操作時會產生2個第2層的數,之後第2層的數操作會產生第3層的數……

總之,在完成了以上的操作時,我們已經按照最優的時間到達了每乙個能到達的點,並在那裡留下了我們的標記。

最後直接輸出cnt[t],也就是到達該位置的最少步數。

說的好像有點多,也無所謂了……

以上只是鄙人的拙見,如果有錯誤、不足之處,還請指正。

騎士飛行棋

include include include include int map 110 bu 1000 char str 4 20 struct node a 3 void f strcpy a 2 name,str m printf 玩家2選擇了 s n n a 2 name printf 人物選...

騎士飛行棋

using system using system.collections.generic using system.linq using system.text namespace 騎士飛行棋 宣告乙個陣列用來存玩家a和玩家b public static string playernames ne...

飛行棋總結

方法名 引數返回值 功能showui無無 顯示遊戲表頭 initmap無無 將放置障礙的位置用數字列出,然後將顯示同一種障礙位置的陣列進行在賦值,1 為一種障礙 2 為一種障礙 3 為一種障礙 等等 drawmap無無 畫地圖 橫行,豎行 drawstringmap int pos string 畫...