Sicily 1153 马的周游问题[Special judge] && sicily 1152

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

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

Problem Source

ZSUACM Team Member


Solution

题意是给定起点,求出一条遍历所有节点的路。

直接dfs就ok啦,注意剪枝时用启发式搜索,先搜索拓展节点少的那个节点。

1152的话改一下棋盘大小就ok啦


#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

int flag, a[105];
bool vis[10][10];

struct dir
{
  int x, y, n;
}d[10];

bool cmp(const dir a, const dir b) {return a.n < b.n;}

int cal(int x, int y)
{
  int i, ans = 0;
  for (i = 0; i < 8; ++i)
  {
    int tx = x + d[i].x;
    int ty = y + d[i].y;
    if (tx >= 0 && tx < 8 && ty >= 0 && ty < 8) ++ans;
  }
  return ans;
}

void dfs(int x, int y, int cur)
{
  if (flag) return;

  int i;
  a[cur] = x + y * 8 + 1;
  if (cur == 63)
  {
    for (i = 0; i < 63; ++i) cout << a[i] << ' ';
    cout << a[63] << endl;
    flag = 1;
    return;
  }
  
  for (i = 0; i < 8; ++i) d[i].n = cal(x+d[i].x, y+d[i].y);
  sort(d, d+8, cmp);
  for (i = 0; i < 8; ++i)
  {
    int tx = x + d[i].x;
    int ty = y + d[i].y;
    if (tx >= 0 && tx < 8 && ty >= 0 && ty < 8 && !vis[tx][ty])
    {
      vis[tx][ty] = true;
      dfs(tx, ty, cur+1);
      vis[tx][ty] = false;
    }
  }
  return;
}

int main()
{
  d[0].x = 1; d[0].y = 2;
  d[1].x = 2; d[1].y = 1;
  d[2].x = 1; d[2].y = -2;
  d[3].x = 2; d[3].y = -1;
  d[4].x = -1; d[4].y = 2;
  d[5].x = -2; d[5].y = 1;
  d[6].x = -1; d[6].y = -2;
  d[7].x = -2; d[7].y = -1;
  int i, st;

  while (cin >> st && st != -1)
  {
    memset(vis, 0, sizeof(vis));
    flag = 0;
    --st;
    vis[st%8][st/8] = true;
    dfs(st % 8, st / 8, 0);
  }

  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值