Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge
在一个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。
输入有若干行。每行一个整数N(1<=N<=30),表示马的起点。最后一行用-1表示结束,不用处理。
对输入的每一个起点,求一条周游线路。对应地输出一行,有30个整数,从起点开始按顺序给出马每次经过的棋盘方格的编号。相邻的数字用一个空格分开。
4 -1
注意:如果起点和输入给定的不同,重复多次经过同一方格或者有的方格没有被经过,都会被认为是错误的。
ZSUACM Team Member
跟1153差不多,数据规模小了,可以去看看我的那篇,这里不做多陈述了:
很久之前做的:0.4s,没有优化的DFS:
#include <stdio.h> #include <string.h> int h[6][7], st[31], now, go[] = {-2, -1, -2, 1, -1, 2, 1, 2, 2, 1, 2, -1, 1, -2, -1, -2}; void horse(int i, int j, int now) { int goi, goj; h[i][j] = 1; st[now] = i * 6 + j + 1; if (now == 29) return; for (int k = 0; k < 16; k += 2) { goi = i + go[k]; goj = j + go[k + 1]; if (goi >= 0 && goi <= 4 && goj >= 0 && goj <= 5 && h[goi][goj] == 0) horse(goi, goj, now + 1); } if (st[now + 1] == 0) { st[now] = 0; h[i][j] = 0; } return; } int main() { int n, i, j; while (scanf("%d", &n), n != -1) { now = 0; memset(h, 0, sizeof(h)); memset(st, 0, sizeof(st)); i = (n - 1) / 6; j = (n - 1) % 6; horse(i, j, now); printf("%d", st[0]); for (i = 1; i < 30; i++) printf(" %d", st[i]); printf("\n"); } return 0; }然后做了1153之后回头重做此题:0s:
#include <stdio.h> #include <algorithm> #include <string.h> #include <vector> using namespace std; bool is_ok; int mapp[5][6]; bool vis[5][6]; int ans[30]; int dir[8][2] = {-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2,-2,-1}; void make_map() { for (int i = 0; i < 5; i++) { for (int j = 0; j < 6; j++) { mapp[i][j] = i * 6 + j + 1; } } } bool is_valid(int i, int j) { if (i < 0 || j < 0 || i > 4 || j > 5 || vis[i][j]) { return false; } return true; } int cal_roads(int ii, int jj) {//计算下一步有多少条路可以走 int counter = 0; for (int i = 0; i < 8; i++) { int next_i = ii + dir[i][0]; int next_j = jj + dir[i][1]; if (is_valid(next_i, next_j)) { counter++; } } return counter; } struct choose { int ii; int jj; int roads; choose() {} choose(int i, int j) { ii = i; jj = j; roads = cal_roads(i, j); } }; bool cmp(choose a, choose b) { return a.roads < b.roads; } void DFS(int from_i, int from_j, int num) { vector<choose> cho; for (int i = 0; i < 8; i++) { int next_i = from_i + dir[i][0]; int next_j = from_j + dir[i][1]; if (is_valid(next_i, next_j)) { cho.push_back(choose(next_i, next_j)); } } if (cho.empty())//这里千万注意,我忘记了没有路的时候是要返回的,弄了一个下午。。 return; sort(cho.begin(), cho.end(), cmp); if (num == 29) { ans[num] = mapp[cho[0].ii][cho[0].jj]; is_ok = true; return; } for (int i = 0; i < (int)cho.size(); i++) { vis[cho[i].ii][cho[i].jj] = true; DFS(cho[i].ii, cho[i].jj, num + 1); if (is_ok) { ans[num] = mapp[cho[i].ii][cho[i].jj]; return; } else { vis[cho[i].ii][cho[i].jj] = false; } } } int main() { int sp; make_map(); while (scanf("%d", &sp) && sp != -1) { memset(vis, false, sizeof(vis)); vis[(sp - 1) / 6][(sp - 1) % 6] = true; memset(ans, 0, sizeof(ans)); ans[0] = sp; is_ok = false; DFS((sp - 1) / 6, (sp - 1) % 6, 1); for (int i = 0; i < 30; i++) { if (i != 0) printf(" "); printf("%d", ans[i]); } printf("\n"); } return 0; }之后发现一个很好玩的现象,其实我自己编了个程序来找,结果找到了成环的路:
于是乎。。
#include <stdio.h> int main(){int r[60]={1,14,25,21,29,18,5,16,27,19,8,4,12,23,10,6,17,30,22,26,13,2,15,28,24,11,3,7,20,9},n,i=30;while(i<60)r[i++]=r[i-30];while(scanf("%d",&n)&&n+1)for(i=0;i<30;i++)if(n==r[i]){printf("%d",n);while(r[++i]-n)printf(" %d",r[i]);printf("\n");}return 0;}好吧我有病。。
原文:http://blog.csdn.net/u012925008/article/details/44596091