【week 4】搜索

1.P1605 迷宫

经典的dfs

#include<bits/stdc++.h>
using namespace std;
const int MAXX=20;
bool book[MAXX][MAXX];
int qix,qiy,zhx,zhy,ans=0,N,M,T;
int fx[4]={0,0,-1,1};
int fy[4]={-1,1,0,0};
void dfs(int x,int y){
	//cout<<x<<"  "<<y<<endl;
	if(x==zhx && y==zhy){
		ans++;
		return ;
	}
	book[x][y]=1;
	for(int i=0;i<4;i++){
		int dx=x+fx[i];
		int dy=y+fy[i];
		if(!book[dx][dy] && dx<=N && dx>=1 && dy<=M && dy>=1)dfs(dx,dy),book[dx][dy]=0;;
		
	} 
}
int main(){
	cin>>N>>M>>T;
	cin>>qix>>qiy>>zhx>>zhy;
	while(T--){
		int a,b;
		cin>>a>>b;
		book[a][b]=1;
	}
	dfs(qix,qiy);
	cout<<ans;
	return 0;
} 

2.P1443 马的遍历

思路同上,只要记录步数和改变走的方式。

#include<bits/stdc++.h>
using namespace std;
struct EVA{
	int x,y,temp;
};
queue<EVA>sat;
int fx[8]={1,2,-1,-2,1,-1,2,-2};
int fy[8]={2,1,-2,-1,-2,2,-1,1};
int mapp[1000][1000],n,m,qix,qiy;
int main(){
	cin>>n>>m;
	cin>>qix>>qiy;
	EVA qi;
	qi.x=qix;
	qi.y=qiy;
	qi.temp=1;
	mapp[qi.x][qi.y]=1;
	sat.push(qi);
	while(!sat.empty()){
		EVA wei=sat.front();
		sat.pop();
		for(int i=0;i<8;i++){
			EVA v;
			v.temp=wei.temp+1;
			v.x=fx[i]+wei.x;
			v.y=fy[i]+wei.y;
			if(v.x>=1 && v.x<=n && v.y>=1 && v.y<=m ){
				if(mapp[v.x][v.y]==0){
					mapp[v.x][v.y]=v.temp;
					sat.push(v);
				}
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cout<<mapp[i][j]-1<<" ";
		}
		cout<<endl;
	}
	return 0;
}

3.幻象迷宫

BFS的题目。

前期的思路:通过1500*1500的大小范围直接排除DFS,然后book标记障碍,book_ex标记所走的路,book_ex的值在每个迷宫中各不相同。

出现问题:超时

原因:1.可能出现穿过墙又穿回来的情况。

解决方案:book_ex记录当前迷宫编号的哈希值,在队列的结构体中加入一个值对应哈希值。

出现问题:超时

原因:2.由于book_ex的值极大概率会互相覆盖(毕竟是在同一迷宫)出现互相蚕食的情况。

解决方案(最终思路):

 代码:

#include<bits/stdc++.h>
using namespace std;
int cnt=0,ansx,ansy;
const int maxx=1600;
int book[maxx][maxx];
int book_ex[maxx][maxx];
const int e_chou_1=114;
const int e_chou_2=514;
struct EVA{
	int x,y,id;
};
int n,m;
int fx[4]={0,0,1,-1};
int fy[4]={1,-1,0,0};
int an_quan=114514;
int main(){
	while(cin>>n>>m){
		cnt=1;
		int js=0;
		memset(book,0,sizeof(book));
		memset(book_ex,0,sizeof(book_ex));
		queue<EVA>sat;
		EVA qi;
		qi.id=cnt;
		bool ans=0;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				char ch;
				cin>>ch;
				if(ch=='#')book[i][j]=1;
				if(ch=='S')qi.x=i,qi.y=j,ansx=i,ansy=j;
			}
		}
		sat.push(qi);
		book_ex[qi.x][qi.y]=1;
		while(!sat.empty()){
			js++;
			//if(js>an_quan)ans=1;
			EVA wei=sat.front();
			sat.pop();
			//cout<<"wei:"<<wei.x<<"   "<<wei.y<<"   "<<wei.id<<endl;
			if(wei.id!=1 && wei.x==ansx && wei.y==ansy)ans=1;
			if(ans)break;
			for(int i=0;i<4;i++){
				EVA v;
				v.x=wei.x+fx[i];
				v.y=wei.y+fy[i];
				v.id=wei.id;
				if(v.x==0)v.x=n,v.id=wei.id-e_chou_1;
				if(v.x==n+1)v.x=1,v.id=wei.id+e_chou_1;
				if(v.y==0)v.y=m,v.id=wei.id-e_chou_2;
				if(v.y==m+1)v.y=1,v.id=wei.id+e_chou_2;
				if(book[v.x][v.y] || book_ex[v.x][v.y] == v.id)continue;
				if(book_ex[v.x][v.y]){
					ans=1;
					break;
				}
				book_ex[v.x][v.y]=v.id;
				sat.push(v);
			}
		}
		cout<<(ans?"Yes\n":"No\n");
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值