逃离迷宫 和 连连看

算法:bfs

逃离迷宫

题目描述
  给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?
输入
  第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中,
  第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列,y1, y2对应行。
输出
  每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。
样例输入
2
5 5
...**
*.**.
.....
.....
*....
1 1 1 1 3
5 5
...**
*.**.
.....
.....
*....
2 1 1 1 3
样例输出
no
yes

代码:

 #include <iostream>
   #include <algorithm>
   #include <queue>
   #include <cstring>
   using namespace std;
   char ch[105][105];
   int map[105][105];
   int n,m,p,q,a[4][2]={0,1,0,-1,1,0,-1,0},x1,y1,num;
   struct dot
   {
   	int x,y,step,temp;
   };
   int bfs()
   {
   	  queue<dot>que;
   	  dot cur,loer;
   	  cur.x=p;cur.y=q;cur.temp=0;cur.step=-1;
   	  memset(map,0,sizeof(map));
   	  que.push(cur);
   	  while(que.size())
   	  {
   	  	loer=que.front();
   	  	que.pop();
   	  	if(loer.x==x1&&loer.y==y1&&loer.temp<=num) return 1;
   	  	for(int i=0;i<4;i++)
   	  	{
   	  		cur=loer;
   	  		cur.x+=a[i][0];
   	  		cur.y+=a[i][1];
   	  		cur.step=i;
   	  		if(cur.step!=loer.step&&loer.step!=-1) cur.temp++;
   	  		if(cur.x>=0&&cur.x<n&&cur.y>=0&&cur.y<m&&ch[cur.x][cur.y]=='.'&&cur.temp<=num)
   	  		{
   	  			if(!map[cur.x][cur.y]||map[cur.x][cur.y]>=cur.temp)
   	  			{
   	  				map[cur.x][cur.y]=cur.temp;
   	  				que.push(cur);
				}
			}
		}
	  }
	  return 0;
   }
   int main()
   {
   	  int t,i,j,k;
   	  cin>>t;
	  while(t--)
	  {
	  	  cin>>n>>m;
	  	  for(i=0;i<n;i++)
	  	  {
	  	  	for(j=0;j<m;j++)
	  	  	cin>>ch[i][j];
		  }
		  cin>>num>>q>>p>>y1>>x1;
		  q--;p--;x1--;y1--;
		  int ans=bfs();
		  if(ans) cout<<"yes"<<endl;
		  else cout<<"no"<<endl;
	  } 
	  return 0;
   }



连连看

Problem Description
“连连看”相信很多人都玩过。没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子。如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子),而且线的转折次数不超过两次,那么这两个棋子就可以在棋盘上消去。不好意思,由于我以前没有玩过连连看,咨询了同学的意见,连线不能从外面绕过去的,但事实上这是错的。现在已经酿成大祸,就只能将错就错了,连线不能从外围绕过。
玩家鼠标先后点击两块棋子,试图将他们消去,然后游戏的后台判断这两个方格能不能消去。现在你的任务就是写这个后台程序。


Input
输入数据有多组。每组数据的第一行有两个正整数n,m(0<n<=1000,0<m<1000),分别表示棋盘的行数与列数。在接下来的n行中,每行有m个非负整数描述棋盘的方格分布。0表示这个位置没有棋子,正整数表示棋子的类型。接下来的一行是一个正整数q(0<q<50),表示下面有q次询问。在接下来的q行里,每行有四个正整数x1,y1,x2,y2,表示询问第x1行y1列的棋子与第x2行y2列的棋子能不能消去。n=0,m=0时,输入结束。
注意:询问之间无先后关系,都是针对当前状态的!


Output
每一组输入数据对应一行输出。如果能消去则输出"YES",不能则输出"NO"。


Sample Input
3 4
1 2 3 4
0 0 0 0
4 3 2 1
4
1 1 3 4
1 1 2 4
1 1 3 3
2 1 2 4
3 4
0 1 4 3
0 2 4 1
0 0 0 0
2
1 1 2 4
1 3 2 3
0 0


Sample Output
YES
NO
NO
NO
NO

YES

代码:

  #include <iostream>
  #include <cstring>
  #include <algorithm>
  #include <queue>
  using namespace std;
  int a[1005][1005];
  int b[1005][1005];
  int n,m,num=2,x1,x2,y1,y2;
  int c[4][2]={0,1,0,-1,1,0,-1,0};
  struct dot
  {
  	int x,y,t,k;
  };
  int bfs()
  {
  	queue<dot>que;
  	dot cur,loer;
  	cur.x=x1;cur.y=y1;cur.k=0;cur.t=-1;
  	memset(b,0,sizeof(b));
  	que.push(cur);
  	while(que.size())
  	{
  		loer=que.front();
  		que.pop();
  		if(loer.x==x2&&loer.y==y2&&loer.k<=num) return 1;
  		if(loer.k>num) continue;
  		for(int i=0;i<4;i++)
  		{
  			cur=loer;
  			cur.x+=c[i][0];
  			cur.y+=c[i][1];
  			cur.t=i;
  			if(cur.t!=loer.t&&loer.t!=-1) cur.k++;
  			if(cur.x>=0&&cur.x<n&&cur.y>=0&&cur.y<m&&a[cur.x][cur.y]==0&&cur.k<=num)
  			{
  				if(!b[cur.x][cur.y]||b[cur.x][cur.y]>=cur.k)
  				{
  					b[cur.x][cur.y]=cur.k;
  					que.push(cur);
				}
			}
		}
	}
	return 0;
  }
  int main()
  {
  	  int i,j,p,q;
  	  while(cin>>n>>m&&n&&m)
  	  {
  	  	for(i=0;i<n;i++)
  	  	{
  	  		for(j=0;j<m;j++)
  	  			cin>>a[i][j];
		}
		cin>>q;
		while(q--)
		{
			cin>>x1>>y1>>x2>>y2;
			x1--;y1--;x2--;y2--;
			if(x1==x2&&y1==y2) 
			{
				cout<<"NO"<<endl;
				continue;
			}
			if(a[x1][y1]==a[x2][y2]&&a[x1][y1]!=0)
			{
				    a[x2][y2]=0;
					int ans=bfs();
			        if(ans) 
					cout<<"YES"<<endl; 
			        else 
						cout<<"NO"<<endl;
					a[x2][y2]=a[x1][y1];
			}
			else cout<<"NO"<<endl;
		}
	  }
	  return 0;
  }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值