医院建筑设计规范2016:C语言 数据结构

来源:百度文库 编辑:查人人中国名人网 时间:2024/04/29 02:55:29
马踏棋盘--国际棋盘 8*8 64格子 马放在任意一个位置走动 要求一次走完64格 不重复走. 马走的规则是--日 马在(I,J) 它可以走到8个位置
(I+2,J+3)(I-2,J+3)(I+2,J-3)(I+2,J-3)
(I+3,J+2)(I+3,J-2)(I-3,J+2)(I+3,J-2)
编写代码 将马的行走路线标出(1-64)

输入空格回车之后就可以出现一个答案;;得你的分可真不容易啊!!!我运行通过...
#include<stdio.h>
int delta_i[]={2,1,-1,-2,-2,-1,1,2};/*存储马各个出口位置相对当前位置行下标的增量数组*/
int delta_j[]={1,2,2,1,-1,-2,-2,-1};
int board[8][8];
int exitn(int i,int j,int s,int a[])//求(i,j)的出口子函数
{
int i1,j1,k,count;
for(count=k=0;k<8;k++)
{
i1=i+delta_i[(s+k)%8];
j1=j+delta_j[(s+k)%8];
if(i1>=0 && i1<8 && j1>=0 &&j1<8 &&board[i1][j1]==0)
a[count++]=(s+k)%8;
}
return count;/*返回出口数*/
}
int next(int i,int j,int s)
{
int m,k,kk,min,a[8],b[8],temp;
m=exitn(i,j,s,a);
if(m==0)return -1;
for(min=9,k=0;k<m;k++)
{
temp=exitn(i+delta_i[a[k]],j+delta_j[a[k]],s,b);/*求(i,j)第a[k]号出口数*/
if(temp<min)
{
min=temp;
kk=a[k];
}
}
return kk;/* */
}
void main()
{
int sx,sy,i,j,step,no,start;
for(sx=0;sx<8;sx++)
for(sy=0;sy<8;sy++)
{
start=0;
do{
for(i=0;i<8;i++)
for(j=0;j<8;j++)board[i][j]=0;
board[sx][sy]=1;
i=sx;j=sy;
for(step=2;step<64;step++)
{
if((no=next(i,j,start))==-1)break;
i+=delta_i[no];
j+=delta_j[no];
board[i][j]=step;
}
if(step>=64)break;
start++;
}while(step<64);
getchar();getchar();
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
printf("%4d",board[i][j]);
printf("\n\n");
}
}
}

这种问题通常用到递归来解决,虽然递归速度慢,但是条理清晰。容易理解。下面是我用递归写的代码,比循环的代码要简短,运行输入开始第一步的坐标,得到运行结果:
////////////////////代码///////////////////////////
#include<stdio.h>

int xLen = 8;//棋盘行数
int yLen = 8;//棋盘列数
int xyLen = xLen * yLen;//最大步数
int arr[8][8];//保存每一个坐标的步数

//每个坐标周围的8个马口相对于当前坐标的相对坐标
int nextXY[8][2] = {{1, 2}, {1, -2}, {-1, 2}, {-1, -2}, {2, 1}, {2, -1}, {-2, 1}, {-2, -1}};

//递归函数,返回0,说明走不通,返回1,说明有下一步
int next(int x, int y, int count = 1)
{
//走过的坐标退出递归
if(arr[x][y] != 0)
return 0;

//到了最后一步,返回1递归完毕
if(count == xyLen)
{
arr[x][y] = xyLen;
return 1;
}

//循环一个坐标附近所有可能的8个坐标
for(int i = 0; i < 8; i++)
{
int nextX = x + nextXY[i][0];
int nextY = y + nextXY[i][1];

//超出棋盘大小的进入下一次循环
if((nextX > (xLen - 1)) || (nextX < 0) || (nextY > (yLen - 1)) || (nextY < 0))
continue;

//标记为走过的坐标,使之不能重复
arr[x][y] = -1;
//递归得到下一个可以走的坐标
if(next(nextX, nextY, count + 1))
{
arr[x][y] = count;
return 1;
}
//走不通的坐标再改回0,使之可以再走
arr[x][y] = 0;
}
return 0;
}
void main()
{
//输入第一步的坐标,不能超过最大行数和列数,不能小于0
int x, y;
while(x < 1 || y < 1 || x > xLen || y > yLen)
{
printf("输入第一步的行数(1~%d):", xLen);
scanf("%d",&x);
printf("输入第一步的列数(1~%d):", yLen);
scanf("%d",&y);
}

//如果有返回则显示
if(next(x - 1, y - 1))
for(int i = 0; i < xLen; i++)
{
for(int j = 0; j < yLen; j++)
printf("%4d",arr[i][j]);
printf("\n\n");
}
else
printf("这一步走不通");

}
////////////////////////////////////////////////////
由于8×8的棋盘递归次数太多,我等不及,我改成6×6的执行了,下面是结果:
输入第一步的行数(1~6):2
输入第一步的列数(1~6):5
10 21 8 31 12 19

7 32 11 20 1 30

22 9 2 29 18 13

33 6 17 26 3 28

16 23 4 35 14 25

5 34 15 24 27 36

厉害,不懂,我好好研究研究