題目鏈接 點擊打開鏈接
題意是一塊石子,從起始位置出發,題目中起始位置爲2,每次移動,它會朝着某一個方向一直運動直到碰到牆或者滑出界外,或者到達終點(題目中是3表示);如果碰到牆,則相應的牆塊消失,並且求停止在牆的前面一個位置,需要再次移動,直到到達目標位置。 每次移動石子,石子都會朝同一個方向移動,遇到下面情況就會停止:
1.石子碰到牆塊
2.石子滑出界外
3.石子到達終點
現在要求石子從起點到達終點最少移動次數,如果移動次數大於10次或者無法移動到目標位置,則遊戲失敗,輸出-1. 如圖所示
改圖中S表示其實位置,G表示終止位置,題目中,牆塊以1表示,S用2表示,G用3表示,空白用0表示 球碰到牆後,牆塊消失,並且球會停在牆塊的前面一個位置,如圖:
圖1到達目標位置情況如下圖,右邊爲最後牆的狀態。
代碼如下:
由於題目中狀態數最多爲20*20,可以用窮舉搜索,另外加了一個剪枝,就是當移動次數大於10搜索停止。
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
#define H 22
#define W 22
#define INF 0xfffffff
int mp[H][W];
int dir[4][2] = {{1,0}, {0,1}, {-1,0}, {0,-1}};
int ans, m, n;
inline bool isWall(int x, int y)
{
if (mp[x][y] == 1) return true;
return false;
}
inline bool outBoard(int x, int y)
{
if (x >= n || x < 0 || y >= m || y < 0)
return true;
return false;
}
inline bool target(int x, int y)
{
if (mp[x][y] == 3)
return true;
return false;
}
void dfs(int x, int y, int cnt)
{
if (cnt > 10 || cnt >= ans) return;
for (int i=0; i<4; i++)
{
int tx = x, ty = y;
if (outBoard(tx + dir[i][0], ty + dir[i][1]) || isWall(tx + dir[i][0], ty + dir[i][1]))
continue;
while (!outBoard(tx, ty) && !isWall(tx, ty) && !target(tx, ty))
{
tx = tx + dir[i][0];
ty = ty + dir[i][1];
}
if (outBoard(tx, ty)) continue;
if (target(tx, ty))
{
if (cnt < ans) ans = cnt;
return;
}
mp[tx][ty] = 0;
dfs(tx-dir[i][0], ty-dir[i][1], cnt+1);
mp[tx][ty] = 1;
}
}
int main()
{
while ( cin >> m >> n && m && n)
{
for (int i=0; i<n; i++)
for (int j=0; j<m; j++)
cin >> mp[i][j];
ans = INF;
for (int i=0; i<n; i++)
for (int j=0; j<m; j++)
if (mp[i][j] == 2)
{
dfs(i, j, 1);
break;
}
if (ans <= 10)
cout << ans << endl;
else
cout << -1 << endl;
}
return 0;
}