[计蒜客]马走日-c++

本文介绍了如何使用C++解决马走日问题,通过深度优先搜索(DFS)算法,计算在给定的n×m棋盘上,马从特定位置出发遍历所有点的不同路径数。文章详细讲解了思路、代码逻辑,并提供了AC代码。

hi!大家好:

        最近几天看了问答,发现有一些人在刷采纳,我就不说是谁了,建议官方处理一下;

        好了,回到正题,最近几天,有个朋友问我了很多BFS的题

我打着打着就有点蒙,难的题对了,简单的题错了。。。就离谱;

于是聪明(nt)的作者就想做点别的找找自信;

随便选了一道题:马走日

题目介绍:

马在中国象棋以日字形规则移动。

请编写一段程序,给定 n×m大小的棋盘,以及马的初始位置 (x, y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。

输入格式

第一行为整数 T(T<10),表示测试数据组数。
每一组测试数据包含一行,为四个整数,分别为棋盘的大小以及初始位置坐标 n,m,x,y。

0≤x≤n−1

0≤y≤m−1

m<10,n<10

输出格式

每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,0 为无法遍历一次;

思路:

这题就是普通的DFS加判断而已,同时数据也不大,所以不需要过多考虑;

代码段逐步理解:

定义变量:

#include<bits/stdc++.h>
using namespace std;
int n,m,ans;
int dx[10] = {1,2,-1,-2,-1,-2, 1, 2};//方向——正常如果无堵马脚,马有八方向,即八个点
int dy[10] = {2,1, 2, 1,-2,-1,-2,-1};
bool vis[15][15];//判断整个棋盘是否都走过了的数组

判断是否整个棋盘的点都被标记为1(被走到过):

bool check() 
{
    for (int i=0;i<n;i++) 
    {
        for (int j=0;j <m;j++) 
        {
            if (!vis[i][j]) return false;
        }
    }    
    return true;
}

DFS函数(核心):

void dfs(int x, int y) 
{
    if (check()) 
    {
        ans++;
        return;
    }
    for (int i = 0; i < 8; i++) //八方向判断
    {
        int tx=x+dx[i];
        int ty=y+dy[i];
        if (0<=tx&&tx<n&&0<=ty&&ty<m&&!vis[tx][ty])//未越界且没走过,才继续dfs
        {
            vis[tx][ty]=true;//设为走过,以免回走
            dfs(tx,ty);
            vis[tx][ty]=false;//清除走过标记
        }
    }
}

main(输入、输出):

int main() 
{
    int x1,y1;
    int t;
    cin>>t;
    while(t--) 
	{        
        cin>>n>>m>>x1>>y1;
        ans=0;
        memset(vis,false,sizeof(vis));//每一组数据测试前清除标记
        vis[x1][y1]=true;
        dfs(x1,y1);
    	cout<<ans<<endl;
    }
    return 0;
}

AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,ans;
int dx[10]={1,2,-1,-2,-1,-2, 1, 2};
int dy[10]={2,1, 2, 1,-2,-1,-2,-1};
bool vis[15][15];
bool check() 
{
    for (int i=0;i<n;i++)
        for (int j=0;j<m;j++) 
            if (!vis[i][j]) return false;
    return true;
}
void dfs(int x, int y) 
{
    if (check()) 
    {
        ans++;
        return;
    }
    for (int i=0;i<8;i++) 
    {
        int tx=x+dx[i];
        int ty=y+dy[i];
        if (0<=tx&&tx<n&&0<=ty&&ty<m&&!vis[tx][ty]) 
        {
            vis[tx][ty]=true;
            dfs(tx,ty);
            vis[tx][ty]=false;
        }
    }
}
int main() 
{
    int x1,y1;
    int t;
    cin>>t;
    while(t--) 
	{        
        cin>>n>>m>>x1>>y1;
        ans=0;
        memset(vis,false,sizeof(vis));
        vis[x1][y1]=true;
        dfs(x1,y1);
    	cout<<ans<<endl;
    }
    return 0;
}

下题再见!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值