Description
在n*n棋盘上,对任一位置上放置的一个马,均能选择一个合适的路线,使得该棋子能按象棋的规则不重复地走过棋盘上的每一位置。
Input
输入第一行为测试数据组数。从第二行开始每行3个整数n(3<n<10)、x、y,代表棋盘的大小,和初始坐标。
Output
输出字典序最小的可行解,无解输出“No solution.”。格式见样例。
Sample Input
16 6 6
Sample Output
Case #1:
7 4 9 12 15 36
10 21 6 3 30 13
5 8 11 14 35 16
22 25 20 31 2 29
19 32 27 24 17 34
26 23 18 33 28 1
分析:比较水的一个题,dfs搜图,配合贪心最小字典序,适当剪下枝基本就能跑出来,注意贪心的时候,马要尽量先往上跑,往上跑的时候先往左跑,这样跑到的第一个数据就是所求字典序最小的那个。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 33;
const int inf = 0x3f3f3f3f;
const int dr[] = { -2, -2, -1, -1, 1, 1, 2, 2 };
const int dc[] = { -1, 1, -2, 2, -2, 2, -1, 1 };
int n, ok, vis[maxn*maxn];
void dfs(int pos, int step) {
if (step == n*n) {
ok = 1;
for (int r = 1; r <= n; r ++) {
for (int c = 1; c <= n; c ++)
printf ("%3d", vis[(r-1)*n+c]);
printf ("\n");
}
return;
}
int r = (pos-1)/n + 1;
int c = pos % n;
if (!c) c = n;
for (int i = 0; i < 8; i++) {
int rr = r + dr[i], cc = c + dc[i], pos1 = (rr-1)*n+cc;
if (rr < 1 || cc < 1 || rr > n || cc > n || vis[pos1]) continue;
vis[pos1] = vis[pos] + 1;
dfs(pos1, step + 1); if (ok) return;
vis[pos1] = 0;
}
}
int main() {
int T, r, c; cin >> T;
for (int tt = 1; tt <= T; tt ++) {
cin >> n >> r >> c;
memset(vis, 0, sizeof vis);
vis[(r-1)*n+c] = 1;
ok = 0;
printf("Case #%d:\n", tt);
dfs((r-1)*n+c, 1);
if (!ok) printf ("No solution.\n");
}
return 0;
}