您的位置:首页 > 其它

逃离迷宫 和 连连看

2016-03-23 22:05 239 查看
算法: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: