题目链接:
http://poj.org/problem?id=3009
题目大意:
一种在宽为M高为N大小的矩阵上玩的冰壶游戏,起点字符为‘2‘,终点字符为‘3‘,矩阵上‘0‘为可移动区域,
‘1‘为石头区域。冰壶刚开始是静止的,每走一步都会选择某个方向运动,而且会沿着该方向一直运动不停,
也不会改变方向,除非冰壶碰到石头或者到达终点,才会停下(这算一步)。冰壶在运动的时候,不能改变方
向。冰壶碰到石头会变成静止状态,这时候石头会破裂,该区域变为可移动区域,而冰壶就可以改变方向了。
冰壶一旦走到终点就不再移动。问:冰壶从起点到终点最少停多少次(走多少步)?
思路:
1)记录起点和终点位置,并将起点和终点标为可移动区域。
2)因为需要找到所有通路中的最短步数,所以用DFS寻找从起点到终点的最短步数。
3)每走一步到静止之后,可选择四个方向,DFS继续下一步。
4)在撞到石头破裂后需要继续下一步,这时候需要回溯回来重新选择方向。
5)冰壶不可以出界。
6)不能超过10步。
AC代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; int vis[25][25]; int N,M; int flag,SumStep; int Sx,Sy,Ex,Ey; int Dire[4][2] = {0,1,0,-1,1,0,-1,0}; void DFS(int x,int y,int step) { int tx,ty; if(step >= 10) //超过10步算失败 return ; for(int i = 0; i < 4; i++) { if(!vis[x+Dire[i][0]][y+Dire[i][1]]) //选择可移动的方向 { tx = x; ty = y; while(!vis[tx+Dire[i][0]][ty+Dire[i][1]]) //移动到障碍点或是边界点前 { tx = tx + Dire[i][0]; ty = ty + Dire[i][1]; if(tx == Ex && ty == Ey) { if(SumStep > step+1) //找到路径 SumStep = step+1; flag = 1; return ; } if(tx < 0 || tx >= N || ty < 0 || ty >= M) //判断越界 break; } if(tx >= 0 && tx < N && ty >= 0 && ty < M && step+1 < 10) //撞上障碍后 { vis[tx+Dire[i][0]][ty+Dire[i][1]] = 0; //石头破裂,变为可移动区域 DFS(tx,ty,step+1); //选择方向,继续移动 vis[tx+Dire[i][0]][ty+Dire[i][1]] = 1; //回溯回来,继续选择上一步方向 } } } } int main() { while(~scanf("%d%d",&M,&N) && (M||N)) { memset(vis,0,sizeof(vis)); for(int i = 0; i < N; i++) { for(int j = 0; j < M; j++) { scanf("%d",&vis[i][j]); if(vis[i][j] == 2) //记录起点位置 { Sx = i; Sy = j; vis[i][j] = 0; } if(vis[i][j] == 3) //记录终点位置 { Ex = i; Ey = j; vis[i][j] = 0; } } } flag = 0; SumStep = 0xffffff0; DFS(Sx,Sy,0); if(!flag) SumStep = -1; printf("%d\n",SumStep); } return 0; }
时间: 2024-10-01 04:29:20