您的位置:首页 > 编程语言 > C语言/C++

算法思考--------骑士走棋盘(c语言)

2014-03-25 23:10 162 查看


一、规则说明
             骑士可以从任意一个位置出发,走法和中国象棋的"马"走法类似,"走日"。问:如何走完所有的位置
二、解法
       
 可以用递归的方法解决,但是纯粹的递归在维度大时没有效率。一个聪明的解法由J.C.Warnsdorft提出:先将最难的位置走完,接下来的路就宽广了
三、代码实现
#include <stdio.h>
int travel(int x, int y);
int board[8][8] = {0}; //代表整个棋盘

int main(void)
{
int startx, starty; //记录起点
int i, j;
printf("输入起始点:");
scanf("%d %d", &startx, &starty);

if(travel(startx, starty))
{
printf("游历完成\n");
}
else
{
printf("游历失败\n");
}

for(i = 0; i < 8; i++) //打印
{
for(j = 0; j < 8; j++)
{
printf("%2d ", board[i][j]);
}
putchar('\n');
}
return 0;
}

int travel(int x, int y)
{
int ktmove1[8] = {-2, -1, 1, 2, 2, 1, -1, -2}; //这两行对应一个点可以走的八个方向的坐标
int ktmove2[8] = {1, 2, 2, 1, -1, -2, -2, -1}; //
int nexti[8] = {0}; //这两行存储的是可走的下一步的坐标
int nextj[8] = {0}; //
int exists[8] = {0}; //记录每个可走下一步的可走下一步个数
int i, j, k, m, l;
int tmpi, tmpj;
int count, min, tmp;
i = x;
j = y;
board[i][j] = 1; //将起点坐标置为1

for(m = 2; m <= 64; m++)//通过循环来标记2-64
{
for(l = 0; l < 8; l++)
exists[l] = 0; //这个数组是每次循环都要重复利用的,所以重置0
l = 0; //这个l也是重复利用的
for(k = 0; k < 8; k++) //通过循环判断一个坐标的八个方向是否可走
{
tmpi = i + ktmove1[k];
tmpj = j + ktmove2[k];
if(tmpi < 0 || tmpj < 0 || tmpi > 7 || tmpj > 7) //通过此来筛选是否可走
continue;
if(board[tmpi][tmpj] == 0)//如果可走,就将可走的坐标存储在nexti,nextj中
{
nexti[l] = tmpi;
nextj[l] = tmpj;
l++; //把下一步可走位置加一
}
}
count = l; //将可走位置的数目赋值给count来进行一下判断
if(count == 0)//没有下一步可走,就返回
{
return 0;
}
else if(count == 1)//只有一个位置可走,就选择这一步,然后继续循环
{
min = 0;
}
else //有多个位置可走时,判断哪一个可走位置的下一步的可走位置最少,就走这一步,意思是把
{  //把最困难的走了,这样接下来的空间就大了,可以走完所有位置的可能性就变大了
for(l = 0; l < count; l++) //同时也说明这种非递归的方法不一定对于所有初始位置都能
{            //走遍全图,因为毕竟这种算法使用概率的原理
for(k = 0; k < 8; k++)
{
tmpi = nexti[l] + ktmove1[k];
tmpj = nextj[l] + ktmove2[k];
if(tmpi < 0 || tmpj < 0 || tmpi > 7 || tmpj > 7)
{
continue;
}
if(board[tmpi][tmpj] == 0)
exists[l]++; //记录可走位置下一步可走位置的个数
}
}
tmp = exists[0];
min = 0;
for(l = 1; l < count; l++)
{
if(exists[l] < tmp) //取得可走位置下一步可走位置最少的那个坐标
{
tmp = exists[l];
min = l;
}
}
}
i = nexti[min];
j = nextj[min];
board[i][j] = m; //将当前步数赋值给那个可走位置下一步可走位置最少的那个坐标
}

return 1;
}
四、效果展示

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息