java马踏棋盘回溯,经典问题----马踏棋盘问题(递归回溯)

问题简述:

国际象棋的棋盘为8*8的方格棋盘。现将”马”放在任意指定的方格中,按照”马”走棋的规则将”马”进行移动。要求每个方格只能进入一次,最终使得”马”走遍棋盘的64个方格。

思路简介:

我们可以根据行走规则,得出在最复杂的情况下,我们可以有8种线路,如图所示:

7df96b0ed2ca81c7c224cff8a5bcf6f5ec2.jpg根据输入的位置,我们对各个情况进行逐一尝试,如果当前选定的位置为合适,则递归进入下一层,再次选择合适的位置;如果有没有下一步合适的地方,则回到上一步,选择另外一种情况。此为一种低效的代码,理论上最多可以有8^64次尝试,速度炒鸡慢,还有一种贪心的优化算法。

基础代码:

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define X 8

#define Y 8

int chess[X][Y];

//找到基于x,y位置的下一个可走位置

int nextxy(int *x, int *y, int count)

{

switch (count)

{

case 7://列举共8种情况

if (*x -1 >=0 && *y +2 <= Y - 1 && chess[*x -1][*y +2] == 0)

{

*x -=1;

*y +=2;

return 1;

}

break;

case 1:

if (*x + 2 <= X - 1 && *y + 1 <= Y - 1 && chess[*x + 2][*y + 1] == 0)

{

*x += 2;

*y += 1;

return 1;

}

break;

case 3:

if (*x + 1 <= X - 1 && *y + 2 <= Y - 1 && chess[*x + 1][*y + 2] == 0)

{

*x += 1;

*y += 2;

return 1;

}

break;

case 0:

if (*x + 2 <= X - 1 && *y - 1 >=0 && chess[*x + 2][*y - 1] == 0)

{

*x += 2;

*y -= 1;

return 1;

}

break;

case 2:

if (*x + 1 <= X - 1 && *y - 2 >=0 && chess[*x + 1][*y -2] == 0)

{

*x += 1;

*y -= 2;

return 1;

}

break;

case 6:

if (*x -1 >=0 && *y -2 >=0 && chess[*x-1][*y -2] == 0)

{

*x -=1;

*y -=2;

return 1;

}

break;

case 4:

if (*x - 2 >= 0 && *y - 1>=0 && chess[*x - 2][*y - 1] == 0)

{

*x -= 2;

*y -= 1;

return 1;

}

break;

case 5:

if (*x - 2 >= 0 && *y + 1 <= Y - 1 && chess[*x - 2][*y + 1] == 0)

{

*x -= 2;

*y += 1;

return 1;

}

break;

default:

break;

}

return 0;

}

int print()//迭代打印矩阵

{

int i, j;

for (i = 0; i < X; i++)

{

for (j = 0; j < Y; j++)

{

printf(" %2d ", chess[i][j]);//%2d为了格式好看

}

printf("\n");

}

printf("\n");

return 0;

}

int travelchessboard(int x, int y, int tag)//tag为当前所选的位置是这是在为马找第几个的落脚点,即层数

{

int x1 = x, y1 = y, flag = 0, count = 0;//count为当前位置可以选择的下一步第几条路

chess[x][y] = tag;//将层数赋值给本为0的位置

if (X*Y == tag)

{

//如果所有位置已经安排好,则打印棋盘

print();

return 1;

}

//找到马的下一个可走目标(x1,y1)如果找到则flag=1,否则为0

flag = nextxy(&x1, &y1, count);

while (0 == flag&&count < 7)//给第一步找路//如果当前位置下一步的路还没走完,则选择另外一条路

{

count++;

flag = nextxy(&x1, &y1, count);//直到路走完或者找到下一个可走的路

}

while (flag)//同上,给后续几步找路,如果第一步没找打路,就直接返回0.

{

if (travelchessboard(x1, y1, tag + 1))//进入寻找下一层的路

{

return 1;

}

//继续找,找到马的下一个可走目标(x1,y1)如果找到 flag=1,否则为0

x1 = x;

y1 = y;

count++;

flag = nextxy(&x1, &y1, count);

while (0 == flag&&count < 7)

{

count++;

flag = nextxy(&x1, &y1, count);

}

}

if (0 == flag)

{

chess[x][y] = 0;//找不到,就复原

}

return 0;

}

int main()

{

int i, j;

clock_t start, finsh;//初始化开始结束时间

start = clock();//开始时间记录

for (i = 0; i < X; i++)//矩阵赋值

{

for (j = 0; j < Y;j++)

{

chess[i][j] = 0;

}

}

if (!travelchessboard(0, 0, 1))//进入函数

{

printf("\nfail");//如果遍历完还没有搜索到合适的路径,打印fail

}

finsh = clock();//结束时间记录

printf("\nthe total time is:%fs\n", (double)(finsh - start) / CLOCKS_PER_SEC);//显示总时间

return 0;

}

建议:千万不要去尝试这个方法,电脑会炸的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值