现在的位置: 首页 > 综合 > 正文

poj3009 dfs + 剪枝

2013年09月09日 ⁄ 综合 ⁄ 共 985字 ⁄ 字号 评论关闭

题意:在矩形冰面进行滑石头游戏,只能上下左右滑,冰面上散步很多障碍,给定石头初始位置和需要到达的终点以及障碍的分布。

          若石头与障碍物相邻,则石头不能向这个方向滑动; 若石头滑动起来后,便会一直沿这个方向滑动,若出界,则游戏失败,若碰到障碍物,则石头停下,障碍物消失,

          若石头到达终点,则游戏结束。注意石头滑动次数不能超过10次,这是很重要的剪枝

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

#define INF 15

int w, h, step[4][2] = {{0, -1}, { -1, 0}, {0, 1}, {1, 0}};
int map[25][25];

inline int min(int a, int b) { return a > b ? b : a; }

int dfs(int x, int y, int stp) //stp记录滑动次数
{
    int tx, ty, tmp = INF;

    if (stp >= 10) return INF; //超过十次,剪枝
    
    for (int i = 0; i < 4; i++)
    {
        bool flag = false;
        tx = x; ty = y;
        while (true) {
            tx += step[i][0]; ty += step[i][1];
            if (tx >= 0 && tx < h && ty >= 0 && ty < w) {
                if (map[tx][ty] == 1) {
                    if (!flag) break;
                    else {
                        map[tx][ty] = 0;
                        tmp = min (tmp, 1 + dfs(tx - step[i][0], ty - step[i][1], stp + 1));
                        map[tx][ty] = 1;
                        break;
                    }
                }
                else if (map[tx][ty] == 3) return 1;
                else { flag = true; }
            }
            else break;
        }
    }
    return tmp;
}

int main()
{
    int i, j, sx, sy;
    while (scanf("%d %d", &w, &h) && w && h)
    {
        for (i = 0; i < h; i++)
            for (j = 0; j < w; j++)
            {
                scanf("%d", &map[i][j]);
                if (map[i][j] == 2)
                {
                    sx = i; sy = j;
                }
            }
        int ans = dfs(sx, sy, 0);
        if (ans > 10) printf("-1\n");
        else printf("%d\n", ans);
    }
    return 0;
}

【上篇】
【下篇】

抱歉!评论已关闭.