跳马问题

1.      跳马问题。要求在64个国际象棋格子,任意位置放一个马,如何不重复地把格子走完。(3)

//////////////////////////////////////////////////////
/*
马(N):每步棋先横走或直走一格,然后再往外斜走一格;或者先斜走一格
,最后再往外横走或竖走一格(即走“日”字)。可以越子,没有"中国象棋
"的"蹩马腿"限制。
*/
#include<iostream>
#include<queue>
#include<stdio.h>
#include<string.h>
#include "queue.h"
using namespace std;
#define MAXN 8
const int MaxQueueSize=64;
struct point {
    int x;//马的x方向
    int y;//马的y方向
};

typedef struct Queue{
    struct point  queue[MaxQueueSize];
    int front;//头指针
    int rear;//尾指针
    int tag;//设置标记位
}SeqCQueue;

//初始化队列操作
void QueueInitiate(SeqCQueue *Q){
    Q->front=0;
    Q->rear=0;
    Q->tag=0;
}

//判断队列是否为空
int QueueNotEmpty(SeqCQueue Q){
    if(Q.front==Q.rear&&Q.tag==0)
        return 0;
    else 
        return 1;
}

//入队操作
void  QueueAppend(SeqCQueue *Q,point  x){
    if(Q->tag==1&&Q->front==Q->rear){
        printf("队列已满,无法插入!\n");
    }else {
        Q->queue[Q->rear]=x;
        Q->rear=(Q->rear+1)%MaxQueueSize;
        Q->tag=1;
    }
}

//出队操作
void QueuePop(SeqCQueue *Q,point  *d){
    if(Q->tag==0&&Q->front==Q->rear){
        printf("队列已空,无元素可以出队列!\n");
    }else {
        *d=Q->queue[Q->front];
        Q->front=(Q->front+1)%MaxQueueSize;
        Q->tag=0;
    }
}



SeqCQueue Q;

int m,n;
int step;//记录马走的步数
int map[MAXN][MAXN];//8*8的国际象棋棋盘
int dir[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};//马理论上所能走全部的位置


//求出该位置的马所能走的步数
int _step(int x,int y){
    int i,xi,yi;
    int count=0;
    for( i=0;i<8;i++){
        xi=x+dir[i][0];
        yi=y+dir[i][1];
        //边界条件以及!map[xi][yi]表示未走过的位置
        if(xi>=0&&xi<=MAXN-1&&yi>=0&&yi<=MAXN-1&&!map[xi][yi])
            count++;
    }
    return count;
}

int BFS(point s)
{
    int i,x,y,temp;
    QueueInitiate(&Q);//初始化队列
    QueueAppend(&Q,s);//入队操作
    point hd ;
    int flag=0 ;
    //当队列非空时,进行广度优先搜索
    while(QueueNotEmpty(Q))
    {
        QueuePop(&Q,&hd);//出队列
        map[hd.x][hd.y]=step++;//标记该位置已走过
        printf("%d,%d\n",hd.x,hd.y);//输出走过的位置
        int minstep=10;//初始的最小步数
        int flag=0;//标记
        //8个方向进行搜索
        for( i=0;i<8;i++){
            x=hd.x+dir[i][0];
            y=hd.y+dir[i][1];
            if(x>=0&&x<=MAXN-1&&y>=0&&y<=MAXN-1&&!map[x][y]){
                //如果小于当前的最小步数,则让队列元素出队列,并让当前的元素入队列
                if(_step(x,y)<minstep){
                    minstep=_step(x,y) ;
                    point t ,th ;
                    t.x=x,t.y=y ;
                    if(flag) QueuePop(&Q,&th) ;//如果是第一次的话,就不用出队列了;
                    QueueAppend(&Q,t) ;
                    flag=1;
                }
            }
        }
    }
    return step-1;
}

int main()
{  cout<<"输入起始位置,以空格作为间距::"<<endl;
    while(scanf("%d%d",&m,&n)!=EOF){
        //判断起始位置是否合法
        if(m<0||m>7||n<0||n>7){
            printf("起始位置不合法!\n\n");
        }else {
            printf("\n");
            memset(map,0,sizeof(map));//将8*8的棋盘全部置为0
            point start;
            start.x=m,start.y=n;
            step=1;
            step=BFS(start);
            //按求出的行走路线,将数字1, 2, 3,…,64依次填入一个8×8的方阵,输出
            for(int i=0;i<MAXN;i++){
                for(int j=0;j<MAXN;j++){
                    printf("%-3d",map[i][j]);
                }
                printf("\n");
            }
            printf("step=%d.\n",step);
            printf("\n");
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

suwu150

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值