C语言算法题(马的遍历问题),请教高手!

thy_funny 2002-06-23 11:03:31
马的遍历问题。在8x8方格的棋盘上从任意指定的位置出发,为马寻找一条走遍棋盘每一格并且只经过一次的路径),我想不用贪婪法而是用普通的回溯法做一下,但是程序却总是说走不通,我认为逻辑上应该没有错,实在是搞不懂,请高手帮忙看一下:
#include <stdio.h>
#include <malloc.h>

#define N 8
#define MAX N * N

typedef struct tagSTACK
{
int i, j;
struct tagSTACK * next;
}STACK;//用来回溯的栈数组的元素结构,i、j为当前这一步,而将下一步的可能走法链接在后面

void print(STACK stk[], int top)
{
int i;

for (i = 0; i < top; i++)
printf ("第%2d步, 走到(i = %d, j = %d)\n", i + 1,
stk[i].i, stk[i].j);
}

void setStk(STACK stk[], int top, int i, int j)
{//将当前所在位置的下一步链接到栈中
STACK * p = (STACK *) malloc (sizeof (STACK));
p->i = i;
p->j = j;
p->next = stk[top].next;
stk[top].next = p;
}

int running(int pace[][N], int i, int j)
{
int top = 0;
STACK stk[MAX], * p;

while (top < N * N - 1)
{
stk[top].i = i;
stk[top].j = j;
stk[top].next = NULL;

if (i + 2 < N && j + 1 < N && !pace[i + 2][j + 1])
setStk (stk, top, i + 2, j + 1);
if (i + 1 < N && j + 2 < N && !pace[i + 1][j + 2])
setStk (stk, top, i + 1, j + 2);
if (i - 1 >= 0 && j + 2 < N && !pace[i - 1][j + 2])
setStk (stk, top, i - 1, j + 2);
if (i - 2 >= 0 && j + 1 < N && !pace[i - 2][j + 1])
setStk (stk, top, i - 2, j + 1);
if (i - 2 >= 0 && j - 1 >= 0 && !pace[i - 2][j - 1])
setStk (stk, top, i - 2, j - 1);
if (i - 1 >= 0 && j - 2 >= 0 && !pace[i - 1][j - 2])
setStk (stk, top, i - 1, j - 2);
if (i + 1 < N && j - 2 >= 0 && !pace[i + 1][j - 2])
setStk (stk, top, i + 1, j - 2);
if (i + 2 < N && j - 1 >= 0 && !pace[i + 2][j - 1])
setStk (stk, top, i + 2, j - 1);

if (stk[top].next == NULL)//从这一步走不下去了,需要回溯
{
do
{
pace[stk[top].i][stk[top].j] = 0;//还原状态
--top;
}while (top >= 0 && stk[top].next == NULL);

if (top < 0) return 0;
}
else
pace[i][j] = 1;

p = stk[top].next;
i = p->i;
j = p->j;

stk[top].next = p->next;//把下面要走的这一步从上一步的链表中删除
free (p);
top++;
}
print (stk, top);
return 1;
}

void main()
{
int pace[N][N], i, j;

for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
pace[i][j] = 0;//初始化状态
INPUT:
printf("请指定从哪一格开始(i,j):");
scanf ("%d,%d", &i, &j);

if (i >= N || j >= N) goto INPUT;

if(!running (pace, i, j))
printf ("从您指定的这一格无法不重复地走遍整个棋盘\n");
}
...全文
372 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
alidiedie 2002-07-08
  • 打赏
  • 举报
回复
对分治法解决该问题的质疑:
这个问题可以简化成图论中的哈密儿顿回路问题,这是图论中仍未解决的问题之一。
并不是所有的棋盘布局都有解的。
schwenk曾巧妙证明下列布局没有解:
m*n(为防止重复,假设m<n)
m,n均为奇数,无解。
m=1,2,4,无解。
m=3,且n=4, 6, 8。无解。

并且:某些情况下一个m*n的矩形棋盘可以扩展成m*(n+4)的 棋盘。

如果用分治法,最后必然要有最小情况,根据上面的限制条件,容易看出8*8的棋盘用分治法不能解决。如果棋盘更大,就另当别论了。
wyb_Ultra 2002-07-08
  • 打赏
  • 举报
回复
To alidiedie(阿里):
你说的条件一点都没错,确实是这样的。但是有一点你可能理解错了,我们并不需要找出回路,只要走完棋盘就可以了,即第一步和最后一步不一定是相邻的那八个位置之一。我一直都有留意这个问题,如果找回路,不用回溯还有什么好的方法?
JackSmart 2002-07-05
  • 打赏
  • 举报
回复
to qiangqiang1112(强强) :
请问,你是李强吗??
qiangqiang1112 2002-07-03
  • 打赏
  • 举报
回复
真不好意思,刚考完试,又在课程设计,等忙了这几天,一定贴!等我几天
qiangqiang1112 2002-07-03
  • 打赏
  • 举报
回复
真不好意思,刚考完试,又在课程设计,等忙了这几天,一定贴!等我几天
Rafaelkl 2002-06-27
  • 打赏
  • 举报
回复
有没有人好歹加一个启发啊,不然判定树的无用节点搜索得太多了
wyb_Ultra 2002-06-24
  • 打赏
  • 举报
回复
To thy_funny (西瓜贩子):
有一个可能,就是你的程序效率实在太低,算一天都算不出来。不要发懒,还用Goto语句!
To qiangqiang1112(强强):
不久前我用过贪婪法+回溯写这个程序,找一个很快,但找出全部路径很慢。我想知道分治法快不快!期待你的算法!
qiangqiang1112 2002-06-24
  • 打赏
  • 举报
回复
普通回溯肯定不好,时间太久了
还是用分治吧
我刚做了不久,考试完了就给把算法写出来
jinjin_hz 2002-06-24
  • 打赏
  • 举报
回复
下面是我的程序,供你参考
#include<stdio.h>
#include<iostream.h>
//#define N 5
int count=1;
int result=1;
bool flag=false;
int succeed=0;
int N;
int** cch;
void travel(int x,int y)
{
cch[x][y]=count++;
if(count==N*N+1){
flag=true;
succeed=1;
//printf("第%i种周游路线\n",result++);
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
printf("%d\t",cch[i][j]);
printf("\n");
}
}else if(succeed==0){
if(x>=2&&y<N-1&&cch[x-2][y+1]==0)travel(x-2,y+1);
if(x>=1&&y<N-2&&cch[x-1][y+2]==0)travel(x-1,y+2);
if(x<N-1&&y<N-2&&cch[x+1][y+2]==0)travel(x+1,y+2);
if(x<N-2&&y<N-1&&cch[x+2][y+1]==0)travel(x+2,y+1);
if(x<N-2&&y>=1&&cch[x+2][y-1]==0)travel(x+2,y-1);
if(x<N-1&&y>=2&&cch[x+1][y-2]==0)travel(x+1,y-2);
if(x>=1&&y>=2&&cch[x-1][y-2]==0)travel(x-1,y-2);
if(x>=2&&y>=1&&cch[x-2][y-1]==0)travel(x-2,y-1);
}
cch[x][y]=0;
count--;
}
void main()
{
int startX,startY;
//输入部分
while(1){
printf("请输入棋盘规模:");
cin>>N;
if(N<1){printf("无效的棋盘,没有周游路径\n");continue;}
cch=new int*[N];
for(int i=0;i<N;i++)
{
cch[i]=new int [N];
for(int j=0;j<N;j++)
cch[i][j]=0;
}
printf("请输入马开始的位置:");
scanf("%i %i",&startX,&startY);
startX--;startY--;
if(startX<0||startX>N-1||startY<0||startY>N-1)
printf("输入非法,请重新输入\n");
else break;
}
//程序主体搜索部分
travel(startX,startY);
for(int i=0;i<N;i++)
delete[]cch[i];
delete[]cch;
if(flag==false)printf("没有周游路径\n");
// printf("请输入任意键继续...........\n");

}
jinjin_hz 2002-06-24
  • 打赏
  • 举报
回复
期待!

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧