1. 程式人生 > 其它 >【BFS】新飛行棋

【BFS】新飛行棋

技術標籤:搜尋bfs

測評地址傳送門
Description

期末考試終於結束了。Andy同學感覺鬆了一口氣,他決定重溫小時候的快樂時光–下飛行棋。但是他弄丟了傳統飛行棋需要的骰子,因此他發明了一種新型的飛行棋遊戲,規則如下:棋盤上有n個格子,由近到遠分別編號為1到n。對於1≤i≤n,第i個格子上寫著一個正整數Ni。當玩家處於第a個格子時,他可以選擇往後走Na步,或者往前倒退Na步。當然如果Na+a>n,那麼他就只能選擇後退;同理如果a−Na<1,那麼他就只能選擇前進。保證不會出現既不能前進又不能後退的格子。
Andy學完程式設計後對一個問題很感興趣:從編號s出發,至少需要經過幾把,可以到達t點?(例如在a點選擇往前走Na步,稱之為一把)。

Input

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

Output

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

Samples
Input Copy

6 6 4
1 2 2 3 1 2

Output

1

Hint

對於前10%的資料,s=t;
對於前40%的資料,n≤200;
對於另外10%的資料,s無法到達t;
對於100%的資料,n≤200000;

Source

石光中學 FCS2018基礎班day 6

多次遇到過這個題了,但之前都沒寫出來,嫌它太麻煩,看了同學寫的部落格,還是感覺迷迷瞪瞪的,今天再次與此題相遇,腦袋中蹦出必須將其解決的想法,再次回去看了同學的部落格,終究不是自己寫的,領悟不到精髓。不過不難解決,換用BFS的思路一發順利將其KO。AC後的感覺,別說,還真棒,哈哈哈哈。

解題思路:

運用常見的BFS思想,將BFS求最短路融合其中,值得注意的一點是,BFS的搜尋方向,無疑,這裡僅有兩個方向供我們搜尋,向前 o r or or 向後,分別判斷向前或向後又沒超出邊界,若在邊界內且向此方向走後的花費最少(即路徑最短),就將此點放入佇列,繼續後面的搜尋,最後依照最短路的方式,輸出目的地到出發地的路徑即可,莫忘判斷不可到達的情況。至此,完結。看程式碼。

上程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
int a[200010];
int n,s,
t; int ans; int dist[200010]; void bfs() { memset(dist,0x3f,sizeof dist); queue<PII> q; q.push({s,a[s]}); dist[s] = 0; while(q.size()) { PII tmp = q.front();q.pop(); int idx = tmp.first; int step = tmp.second; int j = idx + step; if(j <= n && dist[j] > dist[idx] + 1) { dist[j] = dist[idx] + 1; q.push({j,a[j]}); } j = idx - step; if(j >= 1 && dist[j] > dist[idx] + 1) { dist[j] = dist[idx] + 1; q.push({j,a[j]}); } } } int main() { scanf("%d%d%d",&n,&s,&t); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } bfs(); if(dist[t]==0x3f3f3f3f) puts("-1"); else printf("%d\n",dist[t]); return 0; }