P1135 奇怪的電梯

(提早聲明,本篇博客可能質量不如前幾篇好,畢竟連肝四篇博客我已經快吐血了✿◕‿◕✿)ios

看到這道題,第一時間想到的就是:深搜!!數組

因而我打了一個只能獲得20分,剩下都MLE的深搜代碼:函數

#include<iostream>
#include<cstdio>
using namespace std;
int n,m[210],a,b,xq=0,minn=9999;
void dfs(int idx,int cishu){
    if(idx==b){
        xq=1;//若是到達了我麼就用小旗標記一下,以便於最後輸出
        minn=min(minn,cishu);//每次到達想要的那個樓層時,都要取最小值,這樣咱們就能夠獲得只要要按幾回按鈕了。
        return;
    }
        //由於在每一層能作的操做只有兩個,因此咱們作兩個判斷就夠了,若是不越界的話,進行深搜就好啦(●'◡'●)
    if(idx-m[idx]>0){
        dfs(idx-m[idx],cishu+1);
    }
    if(idx+m[idx]<=n){
        dfs(idx+m[idx],cishu+1);
    }
}
int main(){
    scanf("%d%d%d",&n,&a,&b);
    for(int i=1;i<=n;i++){
        scanf("%d",&m[i]);
    }//以上全是輸入
    dfs(a,0);//調用深搜函數
    if(xq!=0) printf("%d\n",minn);//輸出,若是小旗不等於零就說明咱們到達過第b層樓
    else printf("-1\n");//不然,也就是沒有到達過第b層樓,就按照題目要求輸出-1
    return 0;//不要忘記return 0喔
}    

MLE是什麼來着?讓咱們百度一下:優化

 

看到這裏你還不知道該幹什麼嗎!俗話說,優化是個好東西spa

咱們來用一個數組,把咱們判斷過的標記上,而後下次再判斷到這個點咱們就先看這個點有沒有被標記,若是被標記了那也就不用繼續下去了,反正已經判斷過了。code

 

    //數組定義個1000就好啦,反正數據也不大
    hh[idx]=1;//每次hh[idx]都等於1,而後後面進行深搜的時候它就不會被搜到嘍,能夠節省很多時間呢
    if(idx-m[idx]>0&&hh[idx-m[idx]]==0){//判斷idx-m[idx]是否被算過
        dfs(idx-m[idx],cishu+1);//若是沒有被計算過,那麼idx-m[idx],次數+1啦
    }
    if(idx+m[idx]>0&&hh[idx+m[idx]]==0){//判斷idx+m[idx]是否被算過
        dfs(idx+m[idx],cishu+1);//跟上面同樣,若是沒有被計算過,那麼idx+m[idx],次數+1啦
    }
    hh[idx]=0;//最後不要忘了歸零!很重要的!
    //若是你不歸零會影響到後面計算,可能明明這一條路是最小的次數,結果就由於你忘了歸零,成功錯過正確答案

 

可是這樣只有80分......咱們還能怎麼優化呢?blog

若是當前的次數已經大於minn了呢......那麼繼續算下去不久沒有意義了?ci

那咱們就再加一個判斷條件:博客

   hh[idx]=1;
    if(idx-m[idx]>0&&cishu<minn&&hh[idx-m[idx]]==0){
        //加上這個特判就萬事大吉了!若是當前次數已經大於等於minn那繼續算下去就沒有意義了,反正算到最後minn仍是不變,因此咱們只在當前次數小於minn的時候纔算下去
        dfs(idx-m[idx],cishu+1);
    }
    if(idx+m[idx]>0&&cishu<minn&&hh[idx+m[idx]]==0){
        //這個跟上面那個道理是同樣的啦
        dfs(idx+m[idx],cishu+1);
    }
    hh[idx]=0;

最後獻上完整代碼:io

#include<iostream>
#include<cstdio>
using namespace std;
int n,m[210],a,b,xq=0,minn=9999,hh[1010];//minn不能等於很小,否則跟其餘的比小他最小怎麼辦 
void dfs(int idx,int cishu){//深搜函數 
    if(idx==b){//出口,若是當前樓層就是第b層,那麼就讓小旗標記一下,取按鍵次數的最小值,而後返回 
        xq=1;
        minn=min(minn,cishu);
        return;
    }
    hh[idx]=1;//標記idx 
    if(idx-m[idx]>0&&cishu<minn&&hh[idx-m[idx]]==0){
        //次數若是大於等於minn那麼計算下去就沒意義了,反正算到最後minn不會有變化
        //若是hh數組的第idx-m[idx]項沒有被標記,也就是說他沒有被判斷過,咱們就能夠繼續了 
        dfs(idx-m[idx],cishu+1);//進行深搜,次數每次加一不要忘 
    }
    if(idx+m[idx]>0&&cishu<minn&&hh[idx+m[idx]]==0){//這個判斷跟上一個是同樣的,不過一個加一個減 
        dfs(idx+m[idx],cishu+1);//進行深搜,注意這裏是+而不是- 
    }
    hh[idx]=0;//取消標記 
    return;//返回上一層
}
int main(){
    scanf("%d%d%d",&n,&a,&b);
    for(int i=1;i<=n;i++){
        scanf("%d",&m[i]);
    }//以上爲輸入 
    dfs(a,0);//調用函數 
    if(xq!=0) printf("%d\n",minn);//輸出,小旗若是不等於0也就表示咱們到達過第b層,輸出minn就行了 
    else printf("-1\n");//不然小旗等於0,也就是說咱們從未到達過第b層,按照題目要求輸出-1 
    return 0;
}

以上僅是我的對於這道題的所有思路與想法,若是有什麼不對的地方,還請各位大佬及時向我糾正。

相關文章
相關標籤/搜索