POJ 3009 Curling 2.0 {深度优先搜索}

原题

$On Planet MM-21, after their Olympic games this year, curling is getting popular. But the rules are somewhat different from ours. The game is played on an ice game board on which a square mesh is marked. They use only a single stone. The purpose of the game is to lead the stone from the start to the goal with the minimum number of moves.

Fig. 1 shows an example of a game board. Some squares may be occupied with blocks. There are two special squares namely the start and the goal, which are not occupied with blocks. (These two squares are distinct.) Once the stone begins to move, it will proceed until it hits a block. In order to bring the stone to the goal, you may have to stop the stone by hitting it against a block, and throw again.

The movement of the stone obeys the following rules:

At the beginning, the stone stands still at the start square.
The movements of the stone are restricted to x and y directions. Diagonal moves are prohibited.
When the stone stands still, you can make it moving by throwing it. You may throw it to any direction unless it is blocked immediately(Fig. 2(a)).
Once thrown, the stone keeps moving to the same direction until one of the following occurs:
The stone hits a block (Fig. 2(b), (c)).
The stone stops at the square next to the block it hit.
The block disappears.
The stone gets out of the board.
The game ends in failure.
The stone reaches the goal square.
The stone stops there and the game ends in success.
You cannot throw the stone more than 10 times in a game. If the stone does not reach the goal in 10 moves, the game ends in failure.

Under the rules, we would like to know whether the stone at the start can reach the goal and, if yes, the minimum number of moves required.

With the initial configuration shown in Fig. 1, 4 moves are required to bring the stone from the start to the goal. The route is shown in Fig. 3(a). Notice when the stone reaches the goal, the board configuration has changed as in Fig. 3(b).$

这次我就不翻译了,简单的说,你的球在方框里面滚动,注意是滚动不是一格一格地移动,只有遇到障碍才会停止。

有相邻的4个方向可以移动,不能是斜对角等方向。

球如果出界了,则失败;如果滚动了10次以上同样失败。

主要就是这个意思,看看图3就懂了。

思路

这道题和之前有一道一样,都是关于广度优先搜索的,大家可以看看这个:POJ 1979 Red and Black(红与黑)

这里在二维数组中移动的方向和之前的定义一样,图示:

首先需要输入二维数组:

        for (int row = 0; row < H; ++row) {
            for (int col = 0; col < W; ++col) {
                cin >> room[row][col];
            }
        }

找到其中为2的即为起点,将当前的row和col复制相应的起始点(start),然后结束循环。

        // 为2的点为起始点
        for (int row = 0; row < H; ++row) {
            for (int col = 0; col < W; ++col) {
                if (room[row][col] == 2) {
                    sRow = row;
                    sCol = col;
                    break;
                }
            }
        }

因为此时已经不需要这个起始点了,将其重新设置为0,表示可以走。因为有完成的步数要求,所以需要加上一个判断,超过10此输出-1。其中的dfs函数为核心。

        room[sRow][sCol] = 0;
        minStep = 11;
        dfs(sRow, sCol, 0);
        if (minStep > 10) {
            minStep = -1;
        }
        // 输出结果
        cout << minStep << endl;

在dfs函数的开头需要做判断。

    if (step >= 10 || step > minStep) {
        return;
    }

这里的d有4个值,表示4个方向(上、右、下、左),之所以当前的(current)row和col都在for循环开始处,是因为如果走到不能走的地方可以立即返回并重新获得当前(原本)的位置。

    for (int d = 0; d < 4; ++d) {
        int cRow = row;
        int cCol = col;
    }

无论如何都得让点处于该范围之中,其次是判断这个点表示的意思。

while (cRow >= 0 && cRow < H && cCol >= 0 && cCol < W) {
    switch (room[cRow][cCol]) {
    }
}

0表示为空,所以继续往该(d)方向走。

case 0: {
    cRow += direc[d][1];
    cCol += direc[d][0];
    break;
}

3表示为终点,如果step加上当前步骤比之前最小的步数还小,将其赋值给最小步数。

case 3: {
    if (step + 1 < minStep) {
        minStep = step + 1;
    }
    cRow = -1;
    break;
}

1表示为障碍,还原走多的这一步然后进行下一次递归,步数加1,位置还原。

case 1: {
    if (!(cRow - direc[d][1] == row && cCol - direc[d][0] == col)) {
        room[cRow][cCol] = 0;
        dfs(cRow - direc[d][1], cCol - direc[d][0], step + 1);
        room[cRow][cCol] = 1;
    }
    cRow = -1;
    break;
}

默认的情况。

default: {
    break;
}

代码

#include <iostream>
using namespace std;

// 题目中给出的最大宽度和高度
#define MAX_W 20
#define MAX_H 20

// 待输入的宽度和高度以及已走的步数
int W, H;
int step = 0;
int minStep;
int sRow, sCol;

// 待写入的二维数组
int room[MAX_W][MAX_H];
// 顺时针的可走方向
const int direc[4][2] = {
    { 0, -1 },
    { 1,0 },
    { 0, 1 },
    { -1 ,0 },
};

void dfs(const int& row, const int& col, int step) {
    if (step >= 10 || step > minStep) {
        return;
    }
    for (int d = 0; d < 4; ++d) {
        int cRow = row;
        int cCol = col;
        while (cRow >= 0 && cRow < H && cCol >= 0 && cCol < W) {
            switch (room[cRow][cCol]) {
            case 0: {
                cRow += direc[d][1];
                cCol += direc[d][0];
                break;
            }
            case 3: {
                if (step + 1 < minStep) {
                    minStep = step + 1;
                }
                cRow = -1;
                break;
            }
            case 1: {
                if (!(cRow - direc[d][1] == row && cCol - direc[d][0] == col)) {
                    room[cRow][cCol] = 0;
                    dfs(cRow - direc[d][1], cCol - direc[d][0], step + 1);
                    room[cRow][cCol] = 1;
                }
                cRow = -1;
                break;
            }
            default: {
                break;
            }
            }
        }
    }
}

int main()
{
    while (cin >> W >> H, W > 0) {
        // 输入
        for (int row = 0; row < H; ++row) {
            for (int col = 0; col < W; ++col) {
                cin >> room[row][col];
            }
        }
        // 为2的点为起始点
        for (int row = 0; row < H; ++row) {
            for (int col = 0; col < W; ++col) {
                if (room[row][col] == 2) {
                    sRow = row;
                    sCol = col;
                    break;
                }
            }
        }
        room[sRow][sCol] = 0;
        minStep = 11;
        dfs(sRow, sCol, 0);
        if (minStep > 10) {
            minStep = -1;
        }
        // 输出结果
        cout << minStep << endl;
    }
}
时间: 2025-01-26 06:41:40

POJ 3009 Curling 2.0 {深度优先搜索}的相关文章

基于图的深度优先搜索和广度优先搜索java实现

 为了解15puzzle问题,了解了一下深度优先搜索和广度优先搜索.先来讨论一下深度优先搜索(DFS),深度优先的目的就是优先搜索距离起始顶点最远的那些路径,而广度优先搜索则是先搜索距离起始顶点最近的那些路径.我想着深度优先搜索和回溯有什么区别呢?百度一下,说回溯是深搜的一种,区别在于回溯不保留搜索树.那么广度优先搜索(BFS)呢?它有哪些应用呢?答:最短路径,分酒问题,八数码问题等.言归正传,这里笔者用java简单实现了一下广搜和深搜.其中深搜是用图+栈实现的,广搜使用图+队列实现的,代码如下

c-采用深度优先搜索进行扑克牌的排序

问题描述 采用深度优先搜索进行扑克牌的排序 #include<iostream> using namespace std; int count=0; int book[5]; char card[5][2]={'2','C','A','D','A','C','J','C','J','H'}; char a[5][2]; void dfs(int step){ if(step==5){ count++; return ; } for(int i=0;i<5;i++){ if(/*a[ste

人工智能: 自动寻路算法实现(二、深度优先搜索)

前言 本篇文章是机器人自动寻路算法实现的第二章.我们要讨论的是一个在一个M×N的格子的房间中,有若干格子里有灰尘,有若干格子里有障碍物,而我们的扫地机器人则是要在不经过障碍物格子的前提下清理掉房间内的灰尘.具体的问题情景请查看人工智能: 自动寻路算法实现(一.广度优先搜索)这篇文章,即我们这个系列的第一篇文章.在上一篇文章里,我们介绍了通过广度优先搜索算法来实现扫地机器人自动寻路的功能.在这篇文章中,我们要介绍与之相对应的另一种算法:深度优先搜索算法. 项目下载地址 正文 算法介绍 深度优先算法

【算法导论】图的深度优先搜索遍历(DFS)

        关于图的存储在上一篇文章中已经讲述,在这里不在赘述.下面我们介绍图的深度优先搜索遍历(DFS).         深度优先搜索遍历实在访问了顶点vi后,访问vi的一个邻接点vj:访问vj之后,又访问vj的一个邻接点,依次类推,尽可能向纵深方向搜索,所以称为深度优先搜索遍历.显然这种搜索方法具有递归的性质.图的BFS和树的搜索遍历很类似,只是其存储方式不同.         其基本思想为:从图中某一顶点vi出发,访问此顶点,并进行标记,然后依次搜索vi的每个邻接点vj:若vj未被访

算法起步之深度优先搜索

原文:算法起步之深度优先搜索        说完广度优先搜索后,我们来看图的另一种遍历形式,深度优先搜索算法,深度优先总是对刚发现的节点的出阿发边进行探索,直到该节点的所有出发边都被发现为止.一旦所有的出发边都被发现,搜索就回溯到前驱结点,来搜索前驱结点的出发边.反复进行直到全部遍历.我们用递归跟栈两种方式进行实现,其实归根到底递归也是栈实现的.        递归实现:   public class DFS { private boolean[] visited; public void df

【算法导论】有向图的深度优先搜索遍历

        在前面的文章中,我已经讨论了无向图的遍历,现在发现在有向图中,可能会发生无法遍历到所有节点的情况.因此在经历一次深度优先搜索遍历后,如果还存在未被搜索到的节点,则需要再从新的节点开始进行深度优先搜索遍历,直到访问完所有节点. 以下面的有向图为例:         如果从a开始进行深度优先搜索遍历,则会得到  a b c d h g f 后结束,因此我们还要 从未访问到的节点e进行第二次深度优先搜索遍历得到e.在前面的深度优先搜索的基础上,有向图的深度优先搜索程序实现如下: #in

C++深度优先搜索的实现方法_C 语言

本文实例讲述了图的遍历中深度优先搜索的C++实现方法,是一种非常重要的算法,具体实现方法如下: 首先,图的遍历是指从图中的某一个顶点出发,按照某种搜索方法沿着图中的边对图中的所有顶点访问一次且仅访问一次.注意到树是一种特殊的图,所以树的遍历实际上也可以看作是一种特殊的图的遍历.图的遍历主要有两种算法:广度优先搜索(Breadth-First-Search)和深度优先搜索(Depth-First-Search). 一.深度优先搜索(DFS)的算法思想 深度优先搜索算法所遵循的搜索策略是尽可能"深&

C语言通过深度优先搜索来解电梯问题和N皇后问题的示例_C 语言

N皇后问题问题描述: 在n×n格的棋盘上放置彼此不受攻击的n个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上. 需求输入: 给定棋盘的大小n (n ≤ 13) 需求输出: 输出有多少种放置方法. #include <stdio.h> #include <math.h> #define MAX 101 int total = 0; char m[MAX][MAX]

深度优先搜索的图文介绍

1. 深度优先搜索介绍 图的深度优先搜索(Depth First Search),和树的先序遍历比较类似. 它的思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通的顶点都被访问到. 若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止. 显然,深度优先搜索是一个递归的过程. 2. 深度优先搜索图解 2.1 无向图的深度优先搜索