Dfs算法训练

模板

  • n的全排列
#include<iostream>
using namespace std;
int n;
int route[100]; //保存路径的数组
bool visited[100];  //保存是否经过的数组


void dfs(int u) //u就是当前位于搜索的第几层
{
    if(u==n)    //结束判断
    {
        for(int i=0;i<n;i++)
        {
            cout<<route[i]<<" ";
        }
        cout<<endl;
        return;
    }
    for(int i=1;i<=n;i++)   //枚举所有可能的情况
    {
        if(visited[i])  continue;
        visited[i]=true;
        route[u]=i;
        dfs(u+1);   //进行下一层的搜索
        /*恢复现场*/
        visited[i]=false;   //回溯到进入上面那个dfs之前的情况
        // route[u]=0; //这里可以不进行这一步的操作因为下一次做这个的时候会自动覆盖掉
    }
    
}

int main()
{
    cin>>n;
    dfs(0);
    return 0;
}
  • 例子:3的全排列
    在这里插入图片描述

题目训练

1.马走日

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

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

输入格式

第一行为整数 T ,表示测试数据组数。

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

输出格式

每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,若无法遍历棋盘上的所有点则输出 0。

数据范围

1≤T≤9 ,
1≤m,n≤9 ,
0≤x≤n−1 ,
0≤y≤m−1

输入样例:

1
5 4 0 0

输出样例:

32

#include<iostream>
using namespace std;

int dx[]={-1,1,-2,2,-2,2,-1,1}; //  不考虑越界,走日总共有八种移动方法
int dy[]={2,2,1,1,-1,-1,-2,-2}; //  用dx和dy数组来储存走日的时候的坐标变化
bool visited[105][105]; 
int n,m,nm;

int cnt=0;      //  计数


void dfs(int x,int y,int step)
{
    if(step==nm)        //  当步数等于矩阵的长宽相乘,这个时候所有的点都被走过了
    {
        cnt++;
        return;
    }
    for(int i=0;i<8;i++)    //遍历所有走法,8种
    {
        int nx=x+dx[i];
        int ny=y+dy[i];
        if(nx<0||ny<0||nx>n-1||ny>m-1||visited[nx][ny])  continue;  //  越界和已访问的不能访问
        visited[nx][ny]=true;
        dfs(nx,ny,step+1);
        visited[nx][ny]=false;      //  回溯
    }
    
}


int main()
{
    int x,y,t;
    cin>>t;
    for(int i=0;i<t;i++)
    {
        cin>>n>>m>>x>>y;
        for(int i=0;i<n;i++)    //这里注意要把visited数组恢复一下,不然存的东西就是上一次的了,就会导致后面的结果错误。
            for(int j=0;j<m;j++)    visited[i][j]=false;
        nm=n*m;
        cnt=0;
        visited[x][y]=true;
        dfs(x,y,1);
        cout<<cnt<<endl;
    }
}

2.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值