原题

$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;
}
}

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

  1. POJ 3009 Curling 2.0【带回溯DFS】

    POJ 3009 题意: 给出一个w*h的地图,其中0代表空地,1代表障碍物,2代表起点,3代表终点,每次行动可以走多个方格,每次只能向附近一格不是障碍物的方向行动,直到碰到障碍物才停下来,此时障碍物 ...

  2. poj 3009 Curling 2.0 (dfs )

    Curling 2.0 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11879   Accepted: 5028 Desc ...

  3. poj 3009 Curling 2.0

    题目来源:http://poj.org/problem?id=3009 一道深搜题目,与一般搜索不同的是,目标得一直往一个方向走,直到出界或者遇到阻碍才换方向. 1 #include<iostr ...

  4. POJ 3009 Curling 2.0(DFS + 模拟)

    题目链接:http://poj.org/problem?id=3009 题意: 题目很复杂,直接抽象化解释了.给你一个w * h的矩形格子,其中有包含一个数字“2”和一个数字“3”,剩下的格子由“0” ...

  5. POJ 3009 Curling 2.0 回溯,dfs 难度:0

    http://poj.org/problem?id=3009 如果目前起点紧挨着终点,可以直接向终点滚(终点不算障碍) #include <cstdio> #include <cst ...

  6. poj 3009 Curling 2.0( dfs )

    题目:http://poj.org/problem?id=3009 参考博客:http://www.cnblogs.com/LK1994/ #include <iostream> #inc ...

  7. 【POJ】3009 Curling 2.0 ——DFS

    Curling 2.0 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11432   Accepted: 4831 Desc ...

  8. 【原创】poj ----- 3009 curling 2 解题报告

    题目地址: http://poj.org/problem?id=3009 题目内容: Curling 2.0 Time Limit: 1000MS   Memory Limit: 65536K Tot ...

  9. POJ P3009 Curling 2.0 题解

    深搜,向四个方向,在不越界的情况下一直闷头走,直到撞墙.到达终点就输出,没到就回溯. #include<iostream> #include<cstring> #include ...

随机推荐

  1. vue.js中compted与model的区别

    在p便签内写的{{reversemessage}}方法,若js里对应的函数为computed则不需要加上括号 若js里对应的函数为model则应该将{{reversemessage}}改为{{reve ...

  2. 学习《SQL必知必会(第4版)》中文PDF+英文PDF+代码++福达BenForta(作者)

    不管是数据分析还是Web程序开发,都会接触到数据库,SQL语法简洁,使用方式灵活,功能强大,已经成为当今程序员不可或缺的技能. 推荐学习<SQL必知必会(第4版)>,内容丰富,文字简洁明快 ...

  3. centos inotify-rsync配置

    安装 yum -y install inotify-tools yum install rsync innotify说明 inotify介绍-- 是一种强大的.细颗粒的.异步的文件系统监控机制,*&a ...

  4. 带你玩转Visual Studio——性能分析与优化

    找到性能瓶颈 二八法则适合很多事物:最重要的只占其中一小部分,约20%,其余80%的尽管是多数,却是次要的.在程序代码中也是一样,决定应用性能的就那20%的代码(甚至更少).因此优化实践中,我们将精力 ...

  5. CCF模拟 I’m stuck!

    I’m stuck! 时间限制: 1.0s 内存限制: 256.0MB   问题描述 给定一个R行C列的地图,地图的每一个方格可能是'#', '+', '-', '|', '.', 'S', 'T'七 ...

  6. WPF和WinForm的区别, 数据驱动与事件驱动的优势对比

    Winform中针对界面的元素进行操作, 所有业务都关联在当前窗口的后台, 而在此之前, 无奈你是双击事件的添加方式.还是后台绑定事件的方式, 你都需要给每个元素一个固定规范的名称, 然后进行相关的数 ...

  7. 数据库SQL Server2012笔记(四)——多表查询、子查询、分页查询、用查询结果创建新表和外连接

    1.多表查询 1)笛卡尔集: select  *  from  表名1,表名2 select  *  from  表名1.表名2  where   表名1.字段名=表名2.字段名 注: 若有两张表有同 ...

  8. Java io流的学习

    近期几天细致学了Java的io流.本来是打算看视频通过视频来学习的.但是后来发现事实上视频看不怎么懂也感觉不是非常easy上手,所以就通过百度和api文档学习了Java的io流 io流能够有两个分类, ...

  9. Hbuilder开发app实战-识岁06-face++的js实现【完结】

    前言 因为识岁app比較简单.所以这节就完结吧, 当然另一些能够优化完好的地方,可是个人兴趣不是非常大, 有想继续完好的,源代码在这里:https://github.com/uikoo9/shisui ...

  10. Java_Learn

    20180417 集合类 Collection 如果是实现了list接口的集合类,具备的特点是有序,可重复: 如果是实现了set接口的集合类,具备的特点是无序,不可重复: Collection中的方法 ...