题目在http://poj.org/problem?id=3009
因为DFS写的不多,所以这个看似很简单的题目,居然修改补补搞了3个多小时,哎。
题目大意是说在一个迷宫中,我们的小球从起点出发,然后只能被横向和竖向抛出,如果打到障碍物,小球就会停止,同时障碍物也会被击碎。
小球可以抛掷一个方向的前提是:它的前面没有障碍物。
如果小球出界或者抛出次数大于10 都是失败。
例如开始状态是:
小球经过四次抛掷,到达状态:
这样就是成功了。
解答:
题目是明显的DFS,给定其中的一点,然后朝着四个方向搜索,找到一个合适的下一个位置,然后再重复上面的过程。
其中有两处可以做剪枝,一个是 当前的steps数目大于10,另一处是如果当前遍历的steps已经比之前求出来的最小值大,那么则跳过这次遍历。
程序要求求出最小的抛掷次数,可以到达出口。
#include <stdio.h>
#include <memory.h>
#define MAX_GRID 21
int min(int x, int y)
{
return x>y?y:x;
}
struct Grid
{
int r;
int c;
bool operator == (const Grid &b)const
{
return r == b.r && c == b.c;
}
bool operator != (const Grid &b)const
{
return !(*this == b);
}
};
int g_Board[MAX_GRID][MAX_GRID];
int g_nRow, g_nCol;
void DfsSearch(const Grid &start, int steps, int &minSteps)
{
steps ++;
if(steps > 10)
{
return ;
}
//search for four direction;
//search up:
Grid iMove;
Grid newMove;
for( iMove = start, iMove.r-- ; iMove.r >= 0; iMove.r--)
{
if(iMove.r == start.r - 1 && g_Board[iMove.r][iMove.c] == 1)
{
break;
}
if(g_Board[iMove.r][iMove.c] == 3 )
{
minSteps = min(minSteps, steps);
return ;
}
if(g_Board[iMove.r][iMove.c] == 1 && steps < minSteps)
{
g_Board[iMove.r][iMove.c] = 0;
newMove = iMove;
newMove.r++;
DfsSearch(newMove, steps, minSteps);
g_Board[iMove.r][iMove.c] = 1;
break;
}
}
//search down;
for( iMove = start, iMove.r += 1; iMove.r < g_nRow; iMove.r++)
{
if(iMove.r == start.r + 1 && g_Board[iMove.r][iMove.c] == 1)
{
break;
}
if(g_Board[iMove.r][iMove.c] == 3)
{
minSteps = min(minSteps, steps);
return ;
}
if(g_Board[iMove.r][iMove.c] == 1 && steps < minSteps)
{
g_Board[iMove.r][iMove.c] = 0;
newMove = iMove;
newMove.r--;
DfsSearch(newMove, steps, minSteps);
g_Board[iMove.r][iMove.c] = 1;
break;
}
}
//search left
for( iMove = start, iMove.c-- ; iMove.c >= 0; iMove.c--)
{
if(iMove.c == start.c - 1 && g_Board[iMove.r][iMove.c] == 1)
{
break;
}
if(g_Board[iMove.r][iMove.c] == 3)
{
minSteps = min(minSteps, steps);
}
if(g_Board[iMove.r][iMove.c] == 1 && steps < minSteps)
{
g_Board[iMove.r][iMove.c] = 0;
newMove = iMove;
newMove.c++;
DfsSearch(newMove, steps, minSteps);
g_Board[iMove.r][iMove.c] = 1;
break;
}
}
//search right
for( iMove = start, iMove.c++ ; iMove.c < g_nCol; iMove.c++)
{
if(iMove.c == start.c + 1 && g_Board[iMove.r][iMove.c] == 1)
{
break;
}
if(g_Board[iMove.r][iMove.c] == 3)
{
minSteps = min(minSteps, steps);
}
if(g_Board[iMove.r][iMove.c] == 1 && steps < minSteps)
{
g_Board[iMove.r][iMove.c] = 0;
newMove = iMove;
newMove.c--;
DfsSearch(newMove, steps, minSteps);
g_Board[iMove.r][iMove.c] = 1;
break;
}
}
steps--;
}
int main()
{
int i,j,k;
while(scanf("%d%d", &g_nCol, &g_nRow) != EOF)
{
memset(g_Board, 0, sizeof(g_Board));
if(g_nRow == 0 && g_nCol == 0)
{
break;
}
Grid start, end;
for( i = 0; i < g_nRow; i++)
{
for( j = 0; j < g_nCol; j++)
{
scanf("%d", &k);
g_Board[i][j] = k;
if( k == 2)
{
start.r = i;
start.c = j;
}
else if( k == 3)
{
end.r = i;
end.c = j;
}
}
}
int minSteps = 100000000;
DfsSearch(start, 0, minSteps);
if(minSteps == 100000000)
{
printf("-1\n");
}
else
{
printf("%d\n", minSteps);
}
}
return 0;
}