sicily 1152 简单马周游 深度优先搜索及回溯算法

1152. 简单的马周游问题

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge

Description

在一个5 * 6的棋盘中的某个位置有一只马,如果它走29步正好经过除起点外的其他位置各一次,这样一种走法则称马的周游路线,试设计一个算法,从给定的起点出发,找出它的一条周游路线。

为了便于表示一个棋盘,我们按照从上到下,从左到右对棋盘的方格编号,如下所示:

1     2     3       4     5     6

7     8     9       10    11       12

13    14       15    16       17    18

19    20       21    22       23    24

25    26       27    28       29    30

马的走法是“日”字形路线,例如当马在位置15的时候,它可以到达2、4、7、11、19、23、26和28。但是规定马是不能跳出棋盘外的,例如从位置1只能到达9和14。

Input

输入有若干行。每行一个整数N(1<=N<=30),表示马的起点。最后一行用-1表示结束,不用处理。

Output

对输入的每一个起点,求一条周游线路。对应地输出一行,有30个整数,从起点开始按顺序给出马每次经过的棋盘方格的编号。相邻的数字用一个空格分开。

Sample Input

4
-1

Sample Output

注意:如果起点和输入给定的不同,重复多次经过同一方格或者有的方格没有被经过,都会被认为是错误的。

Problem Source

ZSUACM Team Member

Submit

#include <iostream>
#include <map>
#include <stack>
#include <vector>
#include <cstring>
using namespace std;
typedef struct Coordinate {
    int x;
    int y;
} Coor;
bool visited[31];
int loc[9][10]; //此在5*6格子数组中添加额外的行和列,拓展为9*10的数组,即设置边界,便于找到可以前进的节点
map<int, Coor> coors; //用于记录每个位置的坐标 

//获得可以前进的节点,即符合“日”字形,且未访问过
vector<int> getAdjacents(int i, int j) {
    vector<int> result;
    if (loc[i-2][j-1] != 0 && visited[loc[i-2][j-1]] == false)
       result.push_back(loc[i-2][j-1]);
    if (loc[i-2][j+1] != 0 && visited[loc[i-2][j+1]] == false)
       result.push_back(loc[i-2][j+1]);
    if (loc[i-1][j-2] != 0 && visited[loc[i-1][j-2]] == false)
       result.push_back(loc[i-1][j-2]);
    if (loc[i-1][j+2] != 0 && visited[loc[i-1][j+2]] == false)
       result.push_back(loc[i-1][j+2]);
    if (loc[i+1][j-2] != 0 && visited[loc[i+1][j-2]] == false)
       result.push_back(loc[i+1][j-2]);
    if (loc[i+1][j+2] != 0 && visited[loc[i+1][j+2]] == false)
       result.push_back(loc[i+1][j+2]);
    if (loc[i+2][j-1] != 0 && visited[loc[i+2][j-1]] == false)
       result.push_back(loc[i+2][j-1]);
    if (loc[i+2][j+1] != 0 && visited[loc[i+2][j+1]] == false)
       result.push_back(loc[i+2][j+1]);
    return result;
}

void search(int start, int &steps, stack<int> &road) {
     vector<int> adjacents = getAdjacents(coors[start].x, coors[start].y);
     //当没有可以走的下一个格子时
     if (adjacents.size() == 0) {
        //如果已经走了29步,此时需要检测是否已经走完了所有节点
        if (steps == 29) {
           bool complete = true;
           for (int j = 1; j <= 30; j++) {
               if (visited[j] == false) {
                  complete = false;
                  break;
               }
           }
           //是,则回溯输出依次经过的节点
           if (complete == true) {
               vector<int> result;
               while(!road.empty()) {
                   result.push_back(road.top());
                   road.pop();
               }
               for (int j = result.size()-1; j >= 0; j--)
                   cout << result[j] << " ";
               cout << endl;
           } else {
              //否,则在保留已经经过了的节点的栈中删除该节点,同时使步数减一和设置该节点未访问过来使的可以
              //通过其他节点到达该节点
              visited[road.top()] = false;
              steps--;
              road.pop();
           }
        } else {
              //未达到上限的29步,则直接保留已经经过了的节点的栈中删除该节点,同时使步数减一和设置该节点未访问过来使的可以
              //通过其他节点到达该节点
              visited[road.top()] = false;
              steps--;
              road.pop();
        }
     } else {
          //当前节点存在相邻的可以走的节点,则依次深搜遍历相邻节点
          for (int i = 0; i < adjacents.size(); i++) {
              visited[adjacents[i]] = true;
              steps++;
              road.push(adjacents[i]);
              search(road.top(), steps, road);
          }
          //刚开始这里未加 !road.empty(),出现runtime error的错误,因为在找到该路径之后,即上面
          //的for循环跳出之后,此时road已经为空了,所以如果未判断!road.empty会是空的road调用
          //此步是解决本题的关键,即当遍历完一个节点的所有相邻节点后,如果既没有达到遍历完所有节点,即!road.empty
          //相邻节点也没有一个进栈的,即均不合格,则此时应该回溯,将该栈顶节点出栈,同时设置为未访问过,步数减一
          if (!road.empty() && road.top() == start) {
              visited[road.top()] = false;
              steps--;
              road.pop();
          }
     }
}

int main() {
    memset(loc, 0, sizeof(loc));
    int value = 1;
    for (int i = 2; i <= 6; i++) {
        for (int j = 2; j <= 7; j++) {
            coors[value].x = i;
            coors[value].y = j;
            loc[i][j] = value++;
        }
    }

    int start;
    while (cin>>start&&start!=-1) {
          memset(visited, false, sizeof(visited));
          int steps = 0;
          stack<int> road;
          road.push(start);
          visited[road.top()] = true;
          search(road.top(), steps, road);
    }
    return 0;
}
时间: 2024-08-06 20:45:19

sicily 1152 简单马周游 深度优先搜索及回溯算法的相关文章

马的遍历——搜索与回溯

题目描述 Description 中国象棋半张棋盘如图所示.马自左下角往右上角跳.今规定只许往右跳,不许往左跳.比如图4(a)中所示为一种跳行路线,并将所经路线打印出来. 输入输出格式 Input/output 输入格式:无输出格式: 第一行:一个整数total表示第几种跳法 第二行:0,0-->2,1-->3,3-->1,4-->3,5-->2,7-->4,8 输入输出样例 Sample input/output 样例测试点#1 输入样例: 无 输出样例: 1 0,0

搜索与回溯算法

[例]任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和. 当n=7共14种拆分方法: 7=1+1+1+1+1+1+1 7=1+1+1+1+1+2 7=1+1+1+1+3 7=1+1+1+2+2 7=1+1+1+4 7=1+1+2+3 7=1+1+5 7=1+2+2+2 7=1+2+4 7=1+3+3 7=1+6 7=2+2+3 7=2+5 7=3+4 total=14 1 [参考程序] 2 program ex5_3; 3 var a:array[0..100]of integer

深度优先搜索(DFS)详解

深度优先搜索(DFS) [算法入门] 1.前言 深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底,这种尽量往深处走的概念即是深度优先的概念. 你可以跳过第二节先看第三节,:) 2.深度优先搜索VS广度优先搜索 2.1演示深度优先搜索的过程 还是引用上篇文章的样例图,起点仍然是V0,我们修改一下题目意思,只需要让你找出一条V0到V6的道路,而无需

【算法入门】深度优先搜索(DFS)

深度优先搜索(DFS) [算法入门] 1.前言深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底,这种尽量往深处走的概念即是深度优先的概念. 你可以跳过第二节先看第三节,:) 2.深度优先搜索VS广度优先搜索 2.1演示深度优先搜索的过程还是引用上篇文章的样例图,起点仍然是V0,我们修改一下题目意思,只需要让你找出一条V0到V6的道路,而无需最短

POJ 1979 Red and Black【深度优先搜索】

题目链接:http://poj.org/problem?id=1979 题目大意:一个矩形的房间地板被分为w*h个小块,每一个小块不是红的就是黑的,你首先站在一个黑色小块上,你只能朝你的四个方向(上下左右)移动,且不能到达红色的小块上,问你最多能到达多少个小块. 很简单的dfs深度优先搜索 没搜索过一个格子,将该格子设置为红色,之后的搜索就不会再搜索到该格子,就不会造成重复,因为该题有很多数据,记得每次处理数据是初始化各数组及其他数据. 代码如下: #include <iostream> #i

python实现基础的深度优先搜索(DFS, depth first search)解决数的全排列问题

数的全排列,是一个很简单的问题,平时我们用笔用纸就能列出答案,但是数列位多的时候,排列的结果就有非常多了,例如有1,2,3,4,5,6,7,8,9这一个数列,有9个数字,则有9!(9的阶乘)这么多种结果.那是非常大的.今天我就来介绍用深度优先搜索来解决这个数的全排列的问题. 深度优先搜索 首先简单介绍一下深度优先搜索,深度优先搜索的关键在于当下该如何做,至于下一步如何做,就与当下做的一样.深度优先搜索的基本模型为: dfs(step): 判断边界:执行相关操作,返回 尝试每一种可能 for( i

深度优先搜索与广度优先搜索

有两种常用的方法可用来搜索图:即深度优先搜索和广度优先搜索.它们最终都会到达所有连通的顶点.深度优先搜索通过栈来实现,而广度优先搜索通过队列来实现. 深度优先搜索: 为了实现深度优先搜索,首先选择一个起始顶点并需要遵守三个规则:(1) 如果可能,访问一个邻接的未访问顶点,标记它,并把它放入栈中.(2) 当不能执行规则1时,如果栈不空,就从栈中弹出一个顶点.(3) 如果不能执行规则1和规则2,就完成了整个搜索过程. 广度优先搜索:在深度优先搜索中,算法表现得好像要尽快地远离起始点似的.相反,在广度

小橙书阅读指南(十二)——无向图、深度优先搜索和路径查找算法

在计算机应用中,我们把一系列相连接的节点组成的数据结构,叫做图.今天我们将要介绍它的一种形式--无向图,以及针对这种结构的深度优先搜索和路径查找算法. 一.无向图数据结构 接口: /** * 图论接口 */ public interface Graph { /** * 顶点数 * * @return */ int vertexNum(); /** * 边数 * * @return */ int edgeNum(); /** * 向图中添加一条v-w的边 * * @param v * @param

sicily 1024 邻接矩阵与深度优先搜索解题

Description There are N cities and N-1 roads in Magic-Island. You can go from one city to any other. One road only connects two cities. One day, The king of magic-island want to visit the island from the capital. No road is visited twice. Do you know