马周游棋盘(回溯)

马跳棋盘
本文介绍了一个经典的马跳棋盘问题的实现方法,采用回溯法搜索所有可能的路径,并通过C++代码详细展示了如何标记已访问位置及保存路径。该程序能够找出所有可行解并展示在标准输出中。

马跳棋盘的程序,基本的回溯法搜索路径,效率很低。
在路径的打印上,1-n的数字分别代表了每步应该调到的位置。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<stdio.h>
#include<vector>
using namespace std;

#define SIZE 10

struct position
{
    int x,y;
}temp;
/* “日” 字  跳法 */
int dx[] = {-2, -1, 1, 2,  2,  1, -1, -2};
int dy[] = { 1,  2, 2, 1, -1, -2, -2, -1};
/*定义棋盘是否被访问*/
int vis[SIZE+1][SIZE+1];
/*定义棋盘*/
int map[SIZE+1][SIZE+1];
/*保存路径*/
vector<position> path;
int ans;//记录数量


void solve( int x, int y, int num ,int n)
{
    int i,j;
    if( num == n*n )//找到一个可行解
    {
        ans += 1;//解数量+1
        for( i = 0 ; i < path.size() - 1 ; i++ )
        {
            map[path[i].x][path[i].y] = i + 1;
        }
        map[path[path.size()-1].x][path[path.size()-1].y] = i+1;

        for( i = 1 ; i <= n ; i++)
        {
            for( j = 1 ; j <= n ; j++)
            {
                printf("%3d ",map[i][j]);
            }
            puts("");
        }

        printf("继续?");
        system("pause");
    }
    int nextX, nextY;
    for( i = 0 ; i < 7 ; i++ )
    {
        nextX = x + dx[i];
        nextY = y + dy[i];
        if( nextX <= n && nextX  >= 1 && nextY <=n && nextY >= 1 && !vis[nextX][nextY] )
        {
            temp.x = nextX;
            temp.y = nextY;

            vis[nextX][nextY] = 1;//标记被访问点
            path.push_back(temp);//记录path
            solve( nextX, nextY, num+1, n);//寻找下一个点
            vis[nextX][nextY] = 0;
            path.pop_back();//弹出最后一个元素
        }
    }
}

int main()
{
    int n;//棋盘大小
    int Xstart,Ystart;
    puts("请输入棋盘大小 n (1~10) (n=-1退出):");
    while( scanf("%d", &n) == 1 && n != -1 )
    {
        while( !( n <= 10 && n >= 1 ) )
        {
            puts("棋盘大小输入错误,请重新输入(范围1~10)");
            scanf("%d",&n);
            if( n == -1 )   return 0;
        }
        ans = 0;
        memset(vis, 0, sizeof(vis));
        memset(map, 0, sizeof(map));
        path.clear();
        puts("请输入开始探索的起始位置 x,y (范围1-n):");
        scanf("%d,%d", &Xstart, &Ystart);
        while( !( Xstart <= n && Xstart >= 1 && Ystart >= 1 && Ystart <= n ) )
        {
            puts("坐标输入错误,请重新输入(范围1-n)");
            scanf("%d,%d", &Xstart, &Ystart);
        }

        vis[Xstart][Ystart] = 1;
        map[Xstart][Ystart] = 1;
        temp.x = Xstart; temp.y = Ystart;
        path.push_back(temp);
        solve( Xstart, Ystart, 1, n);//work to solve this problem

        printf("本次搜索共发现了%d个可行解\n\n", ans);

        puts("请输入棋盘大小n(n=-1退出):");
    }
}

转载于:https://my.oschina.net/lee24/blog/74324

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值