题目大意:地图上“0”代表空白可滑动区域,“1”代表阻碍物,“2”代表起点,“3”代表终点。冰壶从起点开始可以朝上下左右四个方向滑动,若没有遇到阻碍物或者没有到达终点则不会停止,直到滑出地图。若遇到阻碍物后冰壶会停止在阻碍物前一格,被碰撞的阻碍物会消失。需要注意的是,若在冰壶旁边有障碍物,则不可朝障碍物一侧滑动。求冰壶到达终点的最短滑动次数。若10次滑动不能到达终点,则视为不能到达,输出-1。
思路:用简单的DFS即可完成此题,除此以外还可以用迭代深搜来解决。此处贴出最简单的DFS以供参考。
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
int W,H,sum,end_i,end_j; //W:行 H:列 sum:答案 end_i:终点行 end_j:终点列
int vec[20][20]; //地图
int writeans(int dep) //将某分支深度与现有答案比较
{
if(dep == -1)
return 0;
if(sum == -1 || sum > dep) //某分支深度小于现有答案则更新答案
sum = dep;
return 0;
}
int dfs(int m_i, int m_j, int m_vec[20][20], int dep)
{
if(dep > 10 || (sum != -1 && dep > sum)) //剪枝,步数大于10或者步数大于现有解步数则退出
return 0;
int mm_vec[20][20];
for(int i = 0; i < H; i++) //复制二维数组
for(int j = 0; j < W; j++)
mm_vec[i][j] = m_vec[i][j];
for(int k = 0; k < 4; k++) //超某一方向查看是否可滑动
{
int flag = -1;
int next_i,next_j;
for(int l = 1; l < 20; l++)
{
switch(k)
{
case 0: next_i = m_i - l; next_j = m_j; break;
case 1: next_i = m_i + l; next_j = m_j; break;
case 2: next_i = m_i; next_j = m_j - l; break;
case 3: next_i = m_i; next_j = m_j + l; break;
default: break;
}
if(next_i < 0 || next_i >= H || next_j < 0 || next_j >= W || (l == 1 && mm_vec[next_i][next_j] == 1)) //需要注意的是,若在冰壶旁边有障碍物,则不可朝障碍物一侧滑动
break;
else if(mm_vec[next_i][next_j] == 3) //若遇到终点,则记录答案
{
writeans(dep);
return 0;
}
else if(l != 1 && mm_vec[next_i][next_j] == 1)
{
mm_vec[next_i][next_j] = 0;
flag = k;
switch(k)
{
case 0: next_i += 1; break;
case 1: next_i -= 1; break;
case 2: next_j += 1; break;
case 3: next_j -= 1; break;
default: break;
}
break;
}
}
if(flag != -1)
{
dfs(next_i , next_j, mm_vec, dep + 1);
switch(k) //还原地图
{
case 0: next_i -= 1; break;
case 1: next_i += 1; break;
case 2: next_j -= 1; break;
case 3: next_j += 1; break;
default: break;
}
mm_vec[next_i][next_j] = 1;
}
}
return 0;
}
int main()
{
while(1)
{
cin >> W >> H;
if(W == 0 && H == 0)
break;
sum=-1;
int tmp_i;
int start,end;
for(int i = 0; i < H; i++)
for(int j = 0; j < W; j++)
{
cin >> tmp_i;
vec[i][j] = tmp_i;
if(tmp_i == 2) //记录起点
{
start = i;
end = j;
}
if(tmp_i == 3) //记录终点
{
end_i = i;
end_j = j;
}
}
dfs(start, end, vec, 1);
cout << sum << endl;
}
return 0;
}