題目大意:
給定起點和終點的位置,從起點開始朝一個方向扔石頭,當石頭碰到一個方塊,會停止在方塊的前一個位置,并且這個方塊會消失。
當石頭在一個方向上沒有碰到任何方塊,石頭會飛到Board外,則遊戲失敗。求出從起點開始扔石頭,是否能在10次以内碰到終點的位置。
能則輸出最少的次數,不能則輸出-1。
由于題目隻詢問10次以内是否能碰到終點的位置。那DFS的複雜度就沒有多大了。。
直接枚舉起點的四個方向,會得到四個靜止狀态……重複枚舉即可,求最小次數,也就是求有解時遞歸的最小深度。。
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <assert.h>
#include <time.h>
typedef long long LL;
const int INF = 500000001;
const double EPS = 1e-9;
const double PI = acos(-1.0);
using namespace std;
int w, h, dir[4][2] = {-1,0, 1,0, 0,-1, 0,1}; // 方向數組
int graph[50][50], temp[50][50], ans;
bool check(int x, int y, int k) // 檢查越界
{
if(k == 0 || k == 1)
{
if(x <= 1 || x >= h)
{
return false;
}
}
else if(y <= 1 || y >= w)
{
return false;
}
return true;
}
void dfs(int x, int y, int deep)
{
if(deep >= 10) return false;
for(int i = 0; i < 4; i++) // 枚舉每個位置的四個方向
{
int xx = dir[i][0] + x;
int yy = dir[i][1] + y;
if(graph[xx][yy] != 1)
{
while(graph[xx][yy] != 1)
{
if(graph[xx][yy] == 3)
{
ans = min(ans, deep);
}
xx = dir[i][0] + xx;
yy = dir[i][1] + yy;
}
xx -= dir[i][0];
yy -= dir[i][1];
if(check(xx, yy, i))
{
graph[xx+dir[i][0]][yy+dir[i][1]] = 0; // 撞到後的方塊會消失
dfs(xx, yy, deep + 1);
graph[xx+dir[i][0]][yy+dir[i][1]] = temp[xx+dir[i][0]][yy+dir[i][1]]; // 目前狀态搜尋完畢後把方塊恢複
}
}
}
}
void init() // 初始化邊界
{
for(int i = 0; i < 50; i++)
{
for(int j = 0; j < 50; j++)
{
graph[i][j] = 1;
}
}
}
int main()
{
//freopen("test0.in", "r", stdin);
//freopen("test0.out", "w", stdout);
//srand(time(NULL));
int x, y;
while(~scanf("%d %d", &w, &h), w&&h)
{
init();
ans = 10000;
for(int i = 1; i <= h; i++)
{
for(int j = 1; j <= w; j++)
{
scanf("%d", &graph[i][j]);
if(graph[i][j] == 2)
{
x = i;
y = j;
}
}
}
memcpy(temp, graph, sizeof(graph));
dfs(x, y, 0);
if(ans != 10000)
{
printf("%d\n", ans+1);
}
else
{
printf("-1\n");
}
}
return 0;
}