• P1135 奇怪的电梯


    (提前声明,本篇博客可能质量不如前几篇好,毕竟连肝四篇博客我已经快吐血了✿◕‿◕✿)

    看到这道题,第一时间想到的就是:深搜!!

    于是我打了一个只能得到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
    ",minn);//输出,如果小旗不等于零就说明我们到达过第b层楼
        else printf("-1
    ");//否则,也就是没有到达过第b层楼,就按照题目要求输出-1
        return 0;//不要忘记return 0喔
    }    

    MLE是什么来着?让我们百度一下:

    看到这里你还不知道该干什么吗!俗话说,优化是个好东西

    我们来用一个数组,把我们判断过的标记上,然后下次再判断到这个点我们就先看这个点有没有被标记,如果被标记了那也就不用继续下去了,反正已经判断过了。

        //数组定义个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分......我们还能怎么优化呢?

    如果当前的次数已经大于minn了呢......那么继续算下去不久没有意义了?

    那我们就再加一个判断条件:

       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;

    最后献上完整代码:

    #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
    ",minn);//输出,小旗如果不等于0也就表示我们到达过第b层,输出minn就好了 
        else printf("-1
    ");//否则小旗等于0,也就是说我们从未到达过第b层,按照题目要求输出-1 
        return 0;
    }

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

  • 相关阅读:
    uva11922splay
    获取的二维数组排序
    二维数组排序
    $.extend
    <eq>标签
    datagrid时间插件
    id=%d是什么意思呢?
    获得某一月的第一天,最后一天
    数组合并
    phpexcel 导入导出excel表格
  • 原文地址:https://www.cnblogs.com/dgdger/p/12887786.html
Copyright © 2020-2023  润新知