88888888y

导航

 

题目:https://www.luogu.com.cn/problem/P1135

思路:

直接搜,没越界就搜

但是注意!!!这次的dfs需要剪枝技巧,否则时间上过不去

剪枝1:对当前答案进行判断

如果已经达到目标楼层,再用这层递归搜下去只会徒增搜索时间而不会改变结果

所以在判断完是不是最优解之后,直接用return扔掉

如果当前的按按钮次数已经超过了当前的最优解

那还搜个屁啊,搜了也没有,return丢掉得了

剪枝2:定义一个访问数组v

如果在这个地方搜完之后兜兜转转又回到了这个楼层,那还要分时间出来再走一遍已经走过的路

“何の意味もない”

还搜什么,扔掉得了

#include<bits/stdc++.h>
using namespace std;
int n,a,b,k[201],i,v[201],ans=0x3f3f3f3f;
//对于ans,找到最小值,ans就要尽量大一些
void dfs(int h,int sum){
//h为当前楼层,sum为按按钮次数
	if(h==b){//找到目标
		ans=min(ans,sum);//对比一下看能不能用,毕竟我们找的是最小值
		return;//剪枝
	}
	if(sum>ans){//比原来的最小值大,证明不是最优解
		return;//那还搜个屁
	}
	v[h]=1;//标记
	if(h+k[h]<=n&&!v[h+k[h]]){//没越界
		dfs(h+k[h],sum+1);//开搜
	}
	if(h-k[h]>=1&&!v[h-k[h]]){//没越界
		dfs(h-k[h],sum+1);//开搜
	}
	v[h]=0;//回溯
}
int main(){
	scanf("%d%d%d",&n,&a,&b);
	for(i=1;i<=n;++i){
		scanf("%d",&k[i]);
	}
	memset(v,0,sizeof(v));//记得调零
	v[a]=1;//标记
	dfs(a,0);
	if(ans!=0x3f3f3f3f){//如果ans已经被改过了,证明此问题有解
		printf("%d",ans);//输出
	}
	else{//否则就是无解
		printf("-1");//那还玩个屁
	}
	return 0;
}

题目总结:就是一个坐电梯按按钮的事

dfs可以,但是需要多次剪枝

建议使用bfs(虽然我不会)

posted on 2022-03-12 11:15  88888888y  阅读(42)  评论(0)    收藏  举报