原題出處:洛谷題單
題目:奇怪的電梯
呵呵,有一天我做了一個夢,夢見了一種很奇怪的電梯。大樓的每一層樓都可以停電梯,而且第ii層樓(1 \le i \le N)(1≤i≤N)上有一個數字K_i(0 \le K_i \le N)K i (0≤K i ≤N)。電梯只有四個按鈕:開,關,上,下。上下的層數等於當前樓層上的那個數字。當然,如果不能滿足要求,相應的按鈕就會失靈。例如:3, 3 ,1 ,2 ,53,3,1,2,5代表了K_i(K_1=3,K_2=3,…)K
i (K 1=3,K 2 =3,…),從11樓開始。在11樓,按“上”可以到44樓,按“下”是不起作用的,因爲沒有-2−2樓。那麼,從AA樓到BB樓至少要按幾次按鈕呢?
輸入格式
共二行。
第一行爲33個用空格隔開的正整數,表示N,A,B(1≤N≤200, 1≤A,B≤N)N,A,B(1≤N≤200,1≤A,B≤N)。
第二行爲N個用空格隔開的非負整數,表示Ki。
輸出格式
一行,即最少按鍵次數,若無法到達,則輸出−1。
輸入輸出樣例
輸入 #1
5 1 5
3 3 1 2 5
輸出 #1
3
DFS解法:
1、首先得把題意看懂了,一共n層樓,要從A曾到達B層,因爲電梯的特殊規則,所以,在嘗試的時候,可能會遇到無法到達或者多種方式到達的情況,如果把特殊情況考慮到位起碼可以得到20分:
第一種:A=B時,輸出是0 (10分)
第二種:所有樓層都試了就是沒有一條能到達B,那麼cnt就始終等於它的初始值,這裏你要賦給它一個很大的初始值。(10分)
2、用搜索的思想來解決,就比較簡單了直接套用dfs的搜索框架就行了
(我寫完到這裏的時候,有兩個測試點超時了)
3、解決超時問題就得想想怎麼樣來簡化它,第一,我要找最小值,所以如果在搜索過程中出現的案件次數已經比我之前存好的cnt大了,那麼這個時候就沒必要沿着這條路走了可以直接return,到這裏ok了,可以AC。
#include<bits/stdc++.h>
using namespace std;
int n,A,B,cnt=100001;
int k[210];
bool b[210]={0};//標記樓層是否已經走過
int d[2]={1,-1};//上樓加,下樓減
void dfs(int x,int s)
{
if(x==B) cnt=min(s,cnt);//如果已經到達了
if(s>cnt) return;//如果s大於cnt就不用再繼續了,我們要找的是最小值
//下面是典型的dfs
for(int i=0;i<2;i++){
int xx=x+d[i]*k[x];
if(xx>=1 && xx<= n && b[xx]){
s++;
b[x]=false;
dfs(xx,s);
b[x]=true;//回溯
s--;//回溯
}
}
}
int main(){
cin>>n>>A>>B;
memset(b,true,sizeof(b));
for(int i=1;i<=n;i++) cin>>k[i];
b[A]=false;//標記出發樓層 ,這裏是容易忽略的哦
if(A==B) cnt=0;//注意:如果當前樓層和要到達的樓層是一樣的cnt=0
else dfs(A,0);
if(cnt==100001) cout<<-1;//注意:如果cnt這這個值的話說明沒有找到一條路徑,這裏因爲數值範圍小,所以100001肯定夠了
else cout<<cnt;
return 0;
}
BFS解法見下一篇博文:這道題的BFS解法,簡單易懂