sicily 1153. 马的周游问题

1153. 马的周游问题

Constraints

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

Description

和题目C同样的任务,这里只是把棋盘扩大到标准的国际象棋。对这样一个8 * 8的棋盘用同样的方法编号如下:

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       31    32

33    34       35    36       37    38       39    40

41    42       43    44       45    46       47    48

49    50       51    52       53    54       55    56

57    58       59    60       61    62       63    64

Input

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

Output

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

Sample Input

4-1

Sample Output

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


题目分析

1152的题目,只是棋盘变大了,这时候不优先搜索可能性少的节点,会大大增加其分支的搜索回溯时间
所以将现在可达的位置按照其下一步可达位置的数量排序,
先走可能性最少的路径,从而减少回溯的时间


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <memory.h>

#define ROW 8
#define COL 8
#define ALL 64

struct Node {
  int r, c, next;
};
int path[ALL];
int count;
int visited[ROW][COL];
int dir[8][2] = {1,2,2,1,-1,2,-2,1,-1,-2,-2,-1,1,-2,2,-1};
bool com(Node a, Node b) {
  return a.next < b.next;
}

bool canGo(int r, int c) {
  return 0 <= r && r < ROW && 0 <= c && c < COL && !visited[r][c];
}

void travel(int row, int col) {
//std::cout << row*COL + col + 1 << " ";
  path[count++] = row*COL + col + 1;
  visited[row][col] = true;
  if (count == ALL)
    return ;
  Node nodes[8];
  int nextcount = 0;
  for (int i = 0; i < 8; ++i) {
    int nextr = row + dir[i][0];
    int nextc = col + dir[i][1];
    if (canGo(nextr, nextc)) {
      int nextnext = 0;
      for (int j = 0; j < 8; ++j) {
        if (canGo(nextr+dir[j][0], nextc+dir[j][1]))
          nextnext++;
      }
      nodes[nextcount].r = nextr;
      nodes[nextcount].c = nextc;
      nodes[nextcount].next = nextnext;
//std::cout << nextr*COL + nextc + 1 << " ";
      nextcount++;
    }
  }
  std::sort(nodes, nodes+nextcount, com);

  for (int i = 0; i < nextcount; ++i) {
    travel(nodes[i].r, nodes[i].c);
    if (count == ALL)
      return;
  }

  count--;
  visited[row][col] = false;
}


int main()
{
  int num;
  while(scanf("%d", &num)) {
    if (num == -1)
      break;
    memset(visited, 0, sizeof(visited));
    count = 0;
    travel((num-1)/COL, (num-1)%COL);

    for (int i = 0; i < ALL; ++i)
      if (i == ALL-1)
        printf("%d\n", path[i]);
      else
        printf("%d ", path[i]);
  }
}


运 用 贪 心 算 法 ,vc++ 语 言 编 写 , 可 单 输 出 结 果 【问题描述】 跳问题也称骑士遍历、棋盘问题:在8*8方格的棋盘上,从任意指定的方格出发,为象棋中的寻找一条棋盘每一格并且只经过一次的一条路径。 考虑国际象棋棋盘上某个位置的一只,它是否可能只63正好走过起点的其他63位置各一次?如果有一种这样的法,则称所的这条路线为一条周游路线。试设计一个算法找出这样一条周游路线。 在一个8×8的方格棋盘中,按照国际象棋的行规则从棋盘上的某一方格出发,开始在棋盘周游,如果能不重复地棋盘上的每一个方格, 这样的一条周游路线在数学上被称为国际象棋盘上的哈密尔顿链。请你设计一个程序,从键盘输入一个起始方格的坐标,由计算机自动寻找并打印 【算法描述】 本题有较多方法求解,在此仅对回溯法进行分析。 一只棋盘的某一点,它可以朝8个方向前进,方向向量分别是:(2,1)、(2,-1)、(1,2)、(1,-2)、(-2,1)、(-2,-1)、(-1,2)、(-1,-2)。从中任选择一个方向前进,到达新的位置。在从新的位置选择一个方向前进,继续,直到无法前进为止。无法前进可能有如下原因:下一位置超出边界、下一位置已经被访问过。当已经无法前进时,就回退到上一位置,从新选择一个新的方向前进;如果还是无法前进,就再回退到上一位置……
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值