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