题目就不粘了,题意是这样的:一个带网格的方格板,有两种方格,一种是白色的,一种是网状的。白色表示可以通过,用数字0表示,网状的表示障碍物不能通过,用数字1表示。起点和终点分别在两个白色的上面,分别用数字2、3表示。
目标就是从起点走到终点,且步数小于等于10。
走法和步数计算比较特殊:选定一个方向后,只要是通的就能走下去,三种情况:1、刚好走到终点;2、下一步是障碍物,没法走了,就停下来了,注意,碰到障碍物虽然会停下来了,但是障碍物也跟着没了,这也是不能用bfs的原因,图的结构会发生变化;3、到板子边界了,既没到终点也没障碍物挡着,就出了板子,也就失败了。这样三种情况下,都算作一步,即选定一个方向后到停下来就算做一步。
这样看的话用“滚”代替“走”比较好理解,题目也是用的石头为对象进行的。
有一些易错点:
1、题意没理解清;
2、方格板横竖搞错了,我原来习惯用x、y标记,然后就乱了,就按照题目给的w、h标记了;
3、三种情况的判定容易乱,要注意位置标记;
4、把位置坐标带入数组的时候,要考虑越界的问题,当然这个编译就没过 了。
贴代码:
#include <iostream>
#include <cstdio>
using namespace std;
int map[30][30],w,h,sw,sh,gw,gh,minstep;
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
int notover(int ch,int cw){//没有越界为1
if(ch < h && ch >=0 && cw >=0 && cw < w)
return 1;
return 0;
}
int notacc(int ch,int cw){//不能通行为真
if(notover(ch,cw))
if(!map[ch][cw])
return 0;//可通行为0
else
return 1;//没有越界但是有障碍为1
return 2;//越界为2
}
void dfs(int ch,int cw,int step){
if(step >= 10)
return;
int nh,nw,tmph,tmpw;
for(int i = 0; i<4; i++){
tmph = ch + dir[i][0];
tmpw = cw + dir[i][1];
if(notacc(tmph,tmpw))//下一格就不能通行,没法走步,换个方向
continue;
while(!notacc(tmph,tmpw)){
if(tmph == gh && tmpw == gw)
break;
tmph += dir[i][0];
tmpw += dir[i][1];
}
if(tmph == gh && tmpw == gw){
if(step + 1 < minstep)
minstep = step + 1;
continue;
}
if(!notover(tmph,tmpw))
continue;
nh = tmph - dir[i][0];
nw = tmpw - dir[i][1];
if(nh == gh && nw == gw){
if(step + 1 < minstep)
minstep = step + 1;
continue;
}
if(notacc(tmph,tmpw) == 1){//撞到障碍物
map[tmph][tmpw] = 0;
dfs(nh,nw,step+1);
map[tmph][tmpw] = 1;
}
if(notacc(tmph,tmpw) == 2){//越界了
dfs(nh,nw,step+1);
}
}
return;
}
int main(){
while(1){
scanf("%d %d",&w,&h);
if(!w)
return 0;
minstep = 11;
for(int i = 0; i < h; i++)
for(int j = 0 ;j < w; j++){
scanf("%d",&map[i][j]);
if(map[i][j] == 2){
map[i][j] = 0;
sh = i;
sw = j;
}
if(map[i][j] == 3){
map[i][j] = 0;
gh = i;
gw = j;
}
}
dfs(sh,sw,0);
if(minstep > 10)
cout<<"-1"<<endl;
else
cout<<minstep<<endl;
}
}