zoukankan      html  css  js  c++  java
  • POJ 3009 深度优先搜索

    问题:打冰球。冰球可以往上下左右4个方向走,只有当冰球撞到墙时才会停下来,而墙会消失。当冰球紧贴墙时,不能将冰球往那个方向打。冰球出界就当输,超过10次还没将冰球打到目标位置也当输。求用最小次数将冰球打到目标位置,或输出-1表示输了。

    分析:一般来说,求最小步数之类的迷宫问题都是用BFS解决的,但这题涉及到迷宫状态的变化(墙),BFS要不断记录状态的变化很复杂,不过网上好像也有人用BFS做的。DFS更加适合这种状态一直变化的,只不过要保存最优值而已,其实最优值也方便剪枝(当前步数已经是当前最优值大小但还没到达目的地也就没必要进行下去了)。需要注意的是,这题并不是移动一格,而是一直移动直到遇到障碍物。特别是目标点可能在移动的过程中到达。具体看代码。

    C++代码:

      1 #include <cstdio>
      2 
      3 const int MAX_W = 20;
      4 const int MAX_H = 20;
      5 
      6 //输入
      7 int W, H;
      8 int g[MAX_H][MAX_W];
      9 
     10 //起始
     11 int sx, sy;
     12 //目标
     13 int ex, ey;
     14 //4个方向
     15 int d[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
     16 //最终结果
     17 int result;
     18 
     19 bool inSquare(int x, int y){
     20     return 0 <= x && x < H && 0 <= y && y < W;
     21 }
     22 
     23 //在(x, y)位置上的步数ans
     24 void dfs(int x, int y, int ans){
     25     //若到达目标点
     26     if(x == ex && y == ey){
     27         if(result > ans){
     28             //若有更小值
     29             result = ans;
     30         }
     31         return;
     32     }
     33     //若超过10步,或超过当前最短步数
     34     if(ans == 10 || ans >= result) return;
     35     //深度优先4个方向走
     36     for(int i = 0; i < 4; i ++){
     37         int nx = x + d[i][0], ny = y + d[i][1];
     38         while(inSquare(nx, ny) && g[nx][ny] != 1){
     39             //若此方向能走,则走到尽头,直至出场或撞墙
     40             if(nx == ex && ny == ey){
     41                 //若在过程中到达目标点
     42                 ans ++;
     43                 if(result > ans){
     44                     result = ans;
     45                 }
     46                 return;
     47             }
     48             nx += d[i][0];
     49             ny += d[i][1];
     50         }
     51         if((nx == x + d[i][0] && ny == y + d[i][1]) || !inSquare(nx, ny)){
     52             //此方向不能走,或出场
     53             continue;
     54         }
     55         //撞墙
     56         g[nx][ny] = 0;
     57         ans ++;
     58         dfs(nx - d[i][0], ny - d[i][1], ans);
     59         ans --;
     60         g[nx][ny] = 1;
     61     }
     62 }
     63 
     64 void solve(){
     65     //初始化
     66     result = 11;
     67     //找出起始点与终点
     68     for(int i = 0; i < H; i ++){
     69         for(int j = 0; j < W; j ++){
     70             if(g[i][j] == 2){
     71                 sx = i;
     72                 sy = j;
     73                 g[i][j] = 0;
     74             }
     75             if(g[i][j] == 3){
     76                 ex = i;
     77                 ey = j;
     78             }
     79         }
     80     }
     81     //深度优先搜索
     82     dfs(sx, sy, 0);
     83     if(result == 11)
     84         printf("-1
    ");
     85     else
     86         printf("%d
    ", result);
     87 }
     88 
     89 int main(int argc, char const *argv[]){
     90 
     91     while(scanf("%d %d", &W, &H)){
     92         if(W == 0 && H == 0) break;
     93         for(int i = 0; i < H; i ++){
     94             for(int j = 0; j < W; j ++){
     95                 scanf("%d", &g[i][j]);
     96             }
     97         }
     98         solve();
     99     }
    100     return 0;
    101 }
  • 相关阅读:
    推荐:VisualStudio 2005/2008的“Consolas”字体包
    [转]Calendar 動態產生子控制項的 Event Handler, 模拟__doPostBack() 回发
    Ajax ToolKit ModelPopupExtender应用经验二则
    [转]Calendar 控件日期复选
    ASP.NET偷懒大法六(可空类型的动态赋值)
    弹出层(Div)屏蔽父窗口并且让父窗口变暗
    CSS巧用expression来区分只读文本框
    formValidator用户注册表单自动验证
    基于Session原理的验证码方案
    jQuery解决IE6下PNG图片背景透明问题
  • 原文地址:https://www.cnblogs.com/7hat/p/3592080.html
Copyright © 2011-2022 走看看