首页 > 代码库 > 骑士巡游问题

骑士巡游问题

问题:

  在 n × n 方格的国际象棋棋盘上,马(也称为骑士Knight)从任意指定的方格出发,以跳马规则(横一步竖两步或横两步竖一步),周游棋盘的每一个格子,要求每个格子只能跳过一次。

 

代码:

  思路什么的都在代码里,但是我写的代码太肤浅了, 5*5 的规模都要跑半天。

  所以真切的希望大家能够提出对我算法的批评与指教。

#include<iostream>
#include<fstream>
using namespace std;

//定义了8个方向,N表示右上的那个位置
#define N 0
#define NE 1
#define E 2
#define SE 3
#define S 4
#define SW 5
#define W 6
#define NW 7

struct step {//骑士巡游过的地方
    int x;
    int y;
};

void display(step steps[], int n)
{//展示骑士巡游的过程
    ofstream output("output.txt");
    int patch[10][10]={0};
    for (int i = 1; i <= n*n; i++)
    {
        patch[steps[i].x][steps[i].y]=i;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cout<<patch[i][j]<<"    ";
            output<<patch[i][j]<<"    ";
        }
        cout<<endl;
        output<<endl;
    }
    cout<<endl;
    output<<endl;
}

bool isInside(int n, step place)
{//判断是否走出了地图
    if (place.x<1 || place.x>n || place.y<1 || place.y>n) return false;
    return true;
}

bool isOverlap(int map[][8], step place)
{//判断是否走重了
    if (map[place.x][place.y] == 1) return true;
    return false;
}

step overlook(step now, int dir)
{//往dir方向向前看一步,返回这样走之后的位置
    step then;
    switch (dir)
    {
    case N:then.x = now.x + 1, then.y = now.y - 2; break;
    case NE:then.x = now.x + 2, then.y = now.y - 1; break;
    case E:then.x = now.x + 2, then.y = now.y + 1; break;
    case SE:then.x = now.x + 1, then.y = now.y + 2; break;
    case S:then.x = now.x - 1, then.y = now.y + 2; break;
    case SW:then.x = now.x - 2, then.y = now.y + 1; break;
    case W:then.x = now.x - 2, then.y = now.y - 1; break;
    case NW:then.x = now.x - 1, then.y = now.y - 2; break;
    }
    return then;
}

void patrol(step steps[], int now, step then, int map[][8])
{//从now的位置向dir方向巡游下一步
    steps[now + 1] = then;
    //在map上标记已经走过
    map[steps[now + 1].x][steps[now + 1].y] = 1;
}

void KnightPatrol(int n, int count, step steps[], int map[][8])
{//n表示棋盘规模,count表示骑士已经走过的步数,steps记录骑士巡游过的点,map用来标记地图上每个点有没被走过

    if (count > n*n)
    {//如果骑士巡游过了所有的点
        display(steps, n);
    }

    for (int i = N; i <= NW; i++)
    {//对每个方向遍历

        step then = overlook(steps[count], i);//向i方向眺望一下
        if (isInside(n, then) && !isOverlap(map, then))
        {//如果骑士下一步没有跑到地图外面,且没有走到刚才走过的地方

            patrol(steps, count, then, map);
            for(int k=1;k<=count+1;k++)
            {
                cout<<steps[k].x<<","<<steps[k].y<<" ";
            }
            cout<<endl;
            KnightPatrol(n, count + 1, steps, map);
            map[steps[count+1].x][steps[count+1].y]=0;
        }
    }
}

int main()
{
    int n;
    cin >> n;
    step *steps = new step[n*n + 1];
    steps[1].x = 3;
    steps[1].y = 1;
    int map[8][8] = { 0 };
    map[3][1] = 1;
    KnightPatrol(n, 1, steps, map);
    system("pause");
}

 

骑士巡游问题