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;
}

以上仅是我的对于这道题的所有思路与想法,若是有什么不对的地方,还请各位大佬及时向我纠正。

相关文章
相关标签/搜索