您的位置:首页 > 其它

马遍历棋盘

2008-09-03 08:12 148 查看
【问题描述】
马的遍历问题。在8×8方格的棋盘上,从任意指定方格出发,为马寻找一条走遍棋盘每一格并且只经过一次的一条路径。

马的遍历[/b]
]
/*
对于本题,一般可以采用回溯法,这里采用Warnsdoff策略求解,这也是一种贪婪法,
其选择下一出口的贪婪标准是在那些允许走的位置中,选择出口最少的那个位置。
如马的当前位置(i,j)只有三个出口,他们是位置(i+2,j+1)、(i-2,j+1)和
(i-1,j-2),如分别走到这些位置,这三个位置又分别会有不同的出口,假定这三
个位置的出口个数分别为4、2、3,则程序就选择让马走向(i-2,j+1)位置。

由于程序采用的是一种贪婪法,整个找解过程是一直向前,没有回溯,所以能非常
快地找到解。但是,对于某些开始位置,实际上有解,而该算法不能找到解。对于
找不到解的情况,程序只要改变8种可能出口的选择顺序,就能找到解。改变出口
选择顺序,就是改变有相同出口时的选择标准。以下程序考虑到这种情况,引入变
量start,用于控制8种可能着法的选择顺序。开始时为0,当不能找到解时,就让
start增1,重新找解。细节以下程序。

代码如下:

// Horse.cpp : コンソール アプリケーション用のエントリ ポイントの定義
//

#include "stdafx.h"
#include <stdio.h>
#define INF 100

int board[8][8];
int start;
int mover[] = {-2, -1, 1, 2, 2, 1, -1, -2};
int movec[] = { 1, 2, 2, 1,-1,-2, -2, -1};

int numable(int r, int c, int nexta[])
{
/*返回下次可以找到的增量*/
int i, k, a, b;
int num = 0;
for(i = 0;i <= 7;i++)
{
k = (i + start) % 8;
a = r + mover[k];
b = c + movec[k];
if(a <= 7 && a >= 0 && b >= 0 && b <= 7 && board[a][b] == 0)
{
nexta[num] = k;
num++;
}
}
return num;
}

int number(int r, int c)
{
/*返回下次可以找到的增量的个数*/
int i, k, a, b;
int num = 0;
for(i = 0;i <= 7;i++)
{
k = (i + start) % 8;
a = r + mover[k];
b = c + movec[k];
if(a <= 7 && a >= 0 && b >= 0 && b <= 7 && board[a][b] == 0)
{
num++;
}
}
return num;
}

int next(int r, int c)
{
/*返回下次要找的增量,若是-1没有可以找的位置*/

int nexta[8], num, num1 = 0, minNum, i, k;

minNum = INF;
num = numable(r, c, nexta);

if(num == 0)
{
return -1; //没有出口
}

for(i = 0;i <= num - 1;i++)
{
num1 = number(r + mover[nexta[i]], c + movec[nexta[i]]);

if(num1 <= minNum)
{
minNum = num1;
k = nexta[i];
}
}
return k;
}

int main(int argc, char* argv[])
{
int ber, bec;
int step, caseCounter;
int r, c;
int i, j, k;

printf("Please input the first node:(x y)/n");
while(scanf("%d%d", &ber, &bec) != EOF)//接收起点
{
start = 0;
caseCounter = 1;
while(start <= 7)
{
//初始化
for(i = 0;i <= 7;i++)
for(j = 0;j <= 7;j++)
board[i][j] = 0;

r = ber;
c = bec;

board[r][c] = 1;//起点
step = 2;//下一个位置

while(1)
{
if(step > 64)
{
printf("Case %d:/n", caseCounter++);
for(i = 0;i <= 7;i++)
{
for(j = 0;j <= 7;j++)
{
printf("%2d ", board[i][j]);
}
printf("/n");
}
start++;
break;
}//end if
k = next(r, c);

if(k == -1)
{
start++;
break;
}
r = r + mover[k];
c = c + movec[k];

board[r][c] = step;
step++;
}//end while(1)
}//end while(start <= 7)
}//end while(scanf("%d%d", &ber, &bec) != EOF)

return 0;
}

思想二:递归算法:
// horTest.cpp : コンソール アプリケーション用のエントリ ポイントの定義
//
#include "stdafx.h"
int mover[] = {-2, -1, 1, 2, 2, 1, -1, -2};
int movec[] = {1, 2, 2, 1, -1, -2, -2, -1};
int board[8][8];
int next(int r,int c,int array[8][8],int step)
{
int tempx,tempy;

if (step == 64)
{
return 0;
}
step++;

for(int i = 0; i < 7; i++)
{
tempx = r + mover[i];
tempy = c + movec[i];
if ( tempx >= 0 && tempx <= 7 && tempy >=0 && tempy <= 7 && array[tempx][tempy] == 0)
{
array[tempx][tempy] = step;
if(!next(tempx,tempy,array,step))
{
return 0;
}
}
}

return 1;
}
int main(int argc, char* argv[])
{
int startx,starty;
printf("Please input the start node:x y/n");
scanf("%d%d",&startx,&starty);
board[startx][starty] = 1;//初始位置
next(startx,starty,board,1);
for(int j = 0;j < 8;j++)
{
for(int i = 0;i < 8;i++)
{
printf("%2d ",board[j][i]);
}
printf("/n");
}

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