算法提高 学霸的迷宫
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
学霸抢走了大家的作业,班长为了帮同学们找回作业,决定去找学霸决斗。但学霸为了不要别人打扰,住在一个城堡里,城堡外面是一个二维的格子迷宫,要进城堡必须得先通过迷宫。因为班长还有妹子要陪,磨刀不误砍柴功,他为了节约时间,从线人那里搞到了迷宫的地图,准备提前计算最短的路线。可是他现在正向妹子解释这件事情,于是就委托你帮他找一条最短的路线。
输入格式
第一行两个整数n, m,为迷宫的长宽。
接下来n行,每行m个数,数之间没有间隔,为0或1中的一个。0表示这个格子可以通过,1表示不可以。假设你现在已经在迷宫坐标(1,1)的地方,即左上角,迷宫的出口在(n,m)。每次移动时只能向上下左右4个方向移动到另外一个可以通过的格子里,每次移动算一步。数据保证(1,1),(n,m)可以通过。
输出格式
第一行一个数为需要的最少步数K。
第二行K个字符,每个字符∈{U,D,L,R},分别表示上下左右。如果有多条长度相同的最短路径,选择在此表示方法下字典序最小的一个。
样例输入
Input Sample 1:
3 3
001
100
110
Input Sample 2:
3 3
000
000
000
样例输出
Output Sample 1:
4
RDRD
Output Sample 2:
4
DDRR
数据规模和约定
有20%的数据满足:1<=n,m<=10
有50%的数据满足:1<=n,m<=50
有100%的数据满足:1<=n,m<=500。
1.首先能够根据问题,抽象画出一个图,或者一个数,表示各节点之间的关系
例如:迷宫题从(1,1)开始往下走,有上下左右四种情况。然后从上走有上下左右,从下走有上下左右四个路,脑补成一个树。
2.脑海中有了树,使用广度优先遍历一层层的往下找,找到出口即可
3.做题时,按照题目中给出的条件作图,在遍历符合条件的
总结一句话就是,按照题中约束条件限制的情况下作图,广度优先搜索这个图,然后找结果
思路:
这道题应该能判断出使用BFS不断搜索就能找到最终出口。
按照上面的想法,现在题中给出的条件是1不能走,0可以走。所以在入队管理时,除去上下左右为1的路。其次不能走出房间,最后就是走一个结点,将节点标记已访问。
AC代码
#include
using namespace std;
//图中每个结点具有的特性,x表示行,y表示列,Step表示起点到这个点的路径数,s保存路径
struct node{
int x,y,step;
string s;
};
int n,m;//n*m的迷宫
int vis[501][501];//访问过得要标记
char mp[501][501];//输入结果即作图完成
int dir[4][2] = {{1,0},{0,-1},{0,1},{-1,0}};//上下左右四个方向(1,0)表示行加1,列不变,所以表示向下走
char dic[4] = {'D','L','R','U'};//每次选择路径修改
void bfs(){
queue<node> q;
node a,p,next;
a.x=0;a.y=0;a.step=0;a.s="";vis[0][0]=1;
q.push(a);//首先把起点放进去,当成根节点,图已建立完成,开始BFS
while(!q.empty()){
p=q.front();
if(p.x==n-1&&p.y==m-1){
cout<<p.step<<endl<<p.s<<endl;
break;
}//判断是否搜到出口
q.pop();//出队
//如上面所述,按照作的图来遍历
for(int i=0;i<4;i++){
int xx=p.x+dir[i][0];
int yy=p.y+dir[i][1];//xx,yy表示即将要走的结点 行数,列数,符合条件就走,并入队,修改属性值
if(xx>=0&&xx<n&&yy>=0&&yy<m&&!vis[xx][yy]&&mp[xx][yy]!='1'){
next.x=xx;
next.y=yy;
next.step=p.step+1;
next.s=p.s+dic[i];
vis[xx][yy]=1;
q.push(next);
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++){
scanf("%s",mp[i]);
}
bfs();
return 0;
}
例题
http://acm.hdu.edu.cn/showproblem.php?pid=1548
题意:
就是电梯,每个楼层只能上和下,一个固定的数目,给定一个制定的起始层,目的层,求到达目的层最少按几次上下。
例如,5层电梯,起始层1层,目的层5层
1-5层只能上下 3 3 1 2 5层
输入
5 1 5
3 3 1 2 5
0
输出
3
思路:
总结一句话就是,按照题中约束条件限制的情况下作图,广度优先搜索这个图,然后找结果
还是一样,每到一层,只有两种选择,上或下制定层数,所有图的情况就是一个二叉树了,根据约束条件,遍历中如果上超了,下超了,都不可取
AC代码
#include
using namespace std;
int mp[500];//与迷宫一样,储存图或者说储存约束的条件
struct node{
int x,step;
};//每个结点包含现在的层数以及到此节点走了多少步
int vis[500]={0};
int n,s,d;//n层,s开始d结束
int bfs(int n)
{
queue<node> q;
node p,start,next;
start.x=s;start.step=0;vis[s]=1;
q.push(start);
while(!q.empty()){
p=q.front();
q.pop();
//cout<
if(p.x==d){
return p.step;
break;
}//如果已经访问到目的结点,结束。否的话就是有两种情况,分别判断是否入队
int up=mp[p.x]+p.x;//上的情况
int down=p.x-mp[p.x];//下的情况
if(!vis[up]&&up<=n){
next.x=up;
next.step=p.step+1;
vis[up]=1;
q.push(next);
}
if(!vis[down]&&down>=1){
next.x=down;
next.step=p.step+1;
vis[down]=1;
q.push(next);
}
}
return -1;//没找到目的层,返回-1
}
int main(){
while(scanf("%d",&n)!=EOF&&n){
cin>>s>>d;
memset(vis,0,sizeof(vis));//太坑了,之前没注意这个一直答案错误
for(int i=1;i<=n;i++){
cin>>mp[i];
}
printf("%d\n",bfs(n));
}
}
最后再说一句,作图并非一定是给定一个固定的,现成的图。有可能是需要根据题中所给条件抽象构造出一个图,然后一样进行广搜得出答案