(提前声明,本篇博客可能质量不如前几篇好,毕竟连肝四篇博客我已经快吐血了✿◕‿◕✿)
看到这道题,第一时间想到的就是:深搜!!
于是我打了一个只能得到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; }