编程练习POJ3009

# curling 2.0-poj3009
### 大哥鼎力推荐的最佳区分DFS和BFS的题目,供瞻仰
> 题目描述:冰球游戏,在如下的棋盘中,指定一个起点S、一个终点G,问最少需要多少次操作能使得冰球从S运动到G。冰球的运动遵循如下原则:
> * 只能沿XY方向运动,不能沿斜线
> * 冰球可以被移动的前提是下一个位置不能是block
> * 冰球在某个方向上会保持运动除非出现一下三种情况:遇到block,冰球撞击后block消失;出边界;到达目标点G。
> * 操作数不能超过10次


![pic1](http://poj.org/images/3009_1.gif)


具体样例如下(a)为运动路线,(b)为运动后block的状态
![pic2](http://poj.org/images/3009_3.gif)


> 输入:w,h(w为列数,h为行数)
> hxw的矩阵,矩阵值有三种:
> * 0 空
> * 1 block
> * 2 起点
> * 3 终点


> 输出:最小操作数使得冰球从S到G


### 解题思路:
找最短路径最自然的想法是用BFS,但用BFS解此题,最大的问题在于**block会消失**,这个条件会导致当并行计算多个路径时,每个路径对应的棋盘状态不同,也即BFS对应的每个需要入队列的状态都需要保存棋盘的当前布局,这样带来的开销比较大;而DFS最好的地方在于可以**回溯**,回溯可以使不同的路径独立拥有自己的棋盘状态。


没有任何限制条件的DFS规模是$4^(WxH)$,但是因为`递归深度限制`,所以规模是 $4^10$ 也就是 $10^6$,正好合适!




**因此用dfs解此题**


```
#include
#include
#include
using namespace std;


const int maxw = 25;
const int maxh = 25;
int mp[maxh][maxw];
int sx, sy;
int ex, ey;
int w, h;
int imin = 14;
int dir[4][2] = {{0,-1}, {-1,0}, {0,1}, {1,0}};


bool within(int x, int y){
    return x >= 0 && x < h && y >= 0 && y < w;
}


void dfs(int x, int y, int steps){
    if(steps >= 10) return;//递归函数首先要考虑结束条件!!!
    for(int i = 0; i < 4; ++ i){
        int tmpx = x+dir[i][0], tmpy = y+dir[i][1];
        if(!within(tmpx, tmpy) || mp[tmpx][tmpy] == 1) continue;
        //cout << tmpx << " " << tmpy << endl;
        while(within(tmpx, tmpy) && mp[tmpx][tmpy] != 1){
            if(mp[tmpx][tmpy] == 3){
                imin = min(imin, steps+1);
                return;
            }
            tmpx += dir[i][0];
            tmpy += dir[i][1];
        }
        if(within(tmpx, tmpy) && mp[tmpx][tmpy] == 1){
            mp[tmpx][tmpy] = 0;
            dfs(tmpx-dir[i][0], tmpy-dir[i][1], steps+1);
            mp[tmpx][tmpy] = 1;
        }
    }
}


int main(){
    while(true){
        scanf("%d%d", &w, &h);
        if(w == 0 && h == 0) break;
        for(int i = 0; i < h; ++ i){
            for(int j = 0; j < w; ++ j){
                scanf("%d", &mp[i][j]);
                if(mp[i][j] == 2){
                    sx = i;
                    sy = j;
                }
                if(mp[i][j] == 3){
                    ex = i;
                    ey = j;
                }
            }
        }
        imin = 14;
        //cout << sx << " " << sy << endl;
        dfs(sx, sy, 0); 
        imin = (imin == 14)?-1:imin;
        printf("%d\n", imin);  
    }
    return 0;
}
```

你可能感兴趣的:(BFS)