天天看點

[挑戰程式設計競賽] POJ 3009 - Curling 2.0

題目大意:

給定起點和終點的位置,從起點開始朝一個方向扔石頭,當石頭碰到一個方塊,會停止在方塊的前一個位置,并且這個方塊會消失。

當石頭在一個方向上沒有碰到任何方塊,石頭會飛到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;
}