【算法题解】关于DFS的经典题目与分析

news2025/6/26 3:28:12

目录

  • 1. 全排列问题
  • 2. n皇后问题
  • 3. 递归实现指数型枚举
  • 4. 递归实现组合型枚举
  • 5. 数水坑
  • 6. 打死我也不说
  • 7. 字母顺序归位
  • 8. 不同路径数

1. 全排列问题

题目链接
在这里插入图片描述

#include<iostream>
using namespace std;
const int N=10;

int n;
int path[N];//存储
bool st[N];//状态数组
void dfs(int u)
{
    if(u==n)//递归到最后一个数字
    {
        for(int i=0;i<n;i++)    printf("%d ",path[i]);//将路径打印出来
        puts("");
        return;
    }
    for(int i=1;i<=n;i++)
    {
        if(!st[i])//没有被用过的数
        {
            path[u]=i;//将此数存下
            st[i]=true;//并标记此数用过了
            dfs(u+1);//下一层
            st[i]=false;//恢复现场
        }
    }
}
int main()
{
    cin>>n;
    dfs(0);
    return 0;
}

//当然也可以使用next_permutation

相反还有prev_permutation
代码如下:

#include <iostream>
#include <algorithm>
using namespace std;
int main() {
  int a[10];
  int n;
  cin >> n;
  for(int i = 1;  i<= n; i++) {
  	a[i] = i;
  }
  do {
  	for(int i = 1; i <= n; i++) {
  	cout << "    " <<a[i];
  }
  	cout << endl; 
  }while(next_permutation(a + 1, a + n + 1));
  return 0;
}

对于数字全排列另外一种写法:

#include<stdio.h>
#include<iostream>
#include<algorithm>
int a[10];
using namespace std;
int main()
{
	int n = 0;
	cin >> n;
	int j = 1;
	for (int i = 1; i <= n; i++)
	{
		a[i] = n - i + 1;//a[i]最开始为3 2 1
		j *= i;//共有多少个数
	}
	for (int i = 1; i <= j; i++)
	{
		next_permutation(a + 1, a + n + 1);
		for (int k = 1; k <= n; k++)
		{
			cout << "    " << a[k];
		}
		cout << endl;
	}
	return 0;

}

对于字符串的全排列:

#include <bits/stdc++.h>
using namespace std;

string s;
int main()
{
    cin >> s;
    do {
        cout << s << endl;
    } while(next_permutation(s.begin(), s.end()));
    return 0;
}

2. n皇后问题

题目链接

n−皇后问题是指将 n 个皇后放在 n×n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
在这里插入图片描述
在这里插入图片描述

#include<iostream>
using namespace std;
const int N=20;//防止在udg中溢出
int n;
char g[N][N];
bool col[N],dg[N],udg[N];
void dfs(int u)
{
    if(u==n)//放完了
    {
        for(int i=0;i<n;i++)    puts(g[i]);//一行一行打印
        puts("");
        return;
    }
    for(int i=0;i<n;i++)
    {
       if(!col[i]&&!dg[u+i]&&!udg[n-u+i])//判断列与对角线
       {//在同一对角线上u+i会是同一个值,-u+i会也是同一个值,此处加一个n是为了保证为正
       //类似截距 y=x+b;b=y-x;    y=-x+b;b=x+y;
           g[u][i]='Q';//放置皇后
           col[i]=dg[u+i]=udg[n-u+i]=true;//表示此列/此对角线已经用过了
           dfs(u+1);//下一层
           col[i]=dg[u+i]=udg[n-u+i]=false;
           g[u][i]='.';//恢复现场(因为一开始都是.,所以要恢复为原样)
           
       }
    }
}
int main()
{
   cin>>n;
   for(int i=0;i<n;i++)
   {
    for(int j=0;j<n;j++)
        g[i][j]='.';  //初始化
   }
    
    dfs(0);
    return 0;
}

思考:

  1. n皇后问题中的n至少要4,小于4无法完成
  2. 因为是从上往下放,所以只需要考虑两条对角线和是否同列,不需要考虑同行。 其中i就相当于y竖着 u就相当于x

这里放一个只记录皇后列号的代码(不含具体方案):

#include<iostream>
using namespace std;
const int N=20;
int n;
int ans[N];
bool col[N],dg[N],udg[N];
void dfs(int u)
{
    if(u==n+1)
    {
        for(int i=1;i<=n;i++) printf("%d ",ans[i]);
           cout<<endl;
        return ;
    }
    for(int i=1;i<=n;i++)
    {
        if(!col[i]&&!dg[u+i]&&!udg[n-u+i])
        {
            ans[u]=i;
            col[i]=dg[u+i]=udg[n-u+i]=true;
            dfs(u+1);
            col[i]=dg[u+i]=udg[n-u+i]=false;
           
        }
    }
}
int main()
{
    cin>>n;
    if(n<=3||n>10)
    {
        printf("no solute!");
        return 0;
    }
    dfs(1);
    return 0;
}

3. 递归实现指数型枚举

从 1∼n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。
题目链接
在这里插入图片描述

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=16;
int n;
int st[N];// 状态,记录每个位置当前的状态:0表示还没考虑,1表示选它,2表示不选它
void dfs(int u)
{
    if(u>n)
    {
       for(int i=1;i<=n;i++)
	       if(st[i]==1)//已选   
	       printf("%d ",i);
    printf("\n");
       return; 
    }
    st[u]=2;//不选
    dfs(u+1);
    st[u]=0;//恢复
    
    st[u]=1;//选
    dfs(u+1);
    st[u]=0;
}
int main()
{
   
    scanf("%d",&n);
    dfs(1);
    return 0;
}

4. 递归实现组合型枚举

从 1∼n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案。

题目链接
在这里插入图片描述

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=30;
int n,m;//n个整数中随机选出 m 个
int way[N];
void dfs(int u,int start)//u为当前在选的第几个数,start则表示从几开始
{
    if(u+n-start<m) return ;//剪枝  如果当前比如为u=1,1+5-4<3 那么4 5 肯定不满足
    if(u==m+1)//选完了
    {
        for(int i=1;i<=m;i++)   printf("%d ",way[i]);
        puts("");
        return ;
    }
    
    for(int i=start;i<=n;i++)
    {
        way[u]=i;
        dfs(u+1,i+1);
        way[u]=0;//恢复现场  (用0标记)
    }
   
}
int main()
{
    scanf("%d%d",&n,&m);
    dfs(1,1);
    return 0;
}

5. 数水坑

洛谷题目链接
在这里插入图片描述

**写法1**

#include<iostream>
#include<cstdio>
using namespace std;
int fxx[8]={-1,-1,-1,0,0,1,1,1};
int fxy[8]={-1,0,1,-1,1,-1,0,1};
int n,m,ans;
char a[105][105];
void dfs(int x,int y)
{
    int dx,dy;
     a[x][y]='.';
    for (int i=0;i<8;i++)
    {
        dx=x+fxx[i];
        dy=y+fxy[i];
        if (dx>=1&&dx<=n&&dy>=1&&dy<=m&&a[dx][dy]=='W')
            dfs(dx,dy);
    }
}
int main()
{
    scanf("%d %d\n",&n,&m);
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
            cin>>a[i][j];
    }
    ans=0;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
        {
            if (a[i][j]=='W')
            {
                ans++;
                dfs(i,j);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}



**写法2**


#include<iostream>
#include<cstdio>
using namespace std;
int n,m,ans;
char a[105][105];
void dfs(int x,int y)
{
    int dx,dy;
     a[x][y]='.';
    for(int fx=-1;fx<=1;fx++)
    {
        for(int fy=-1;fy<=1;fy++)
        { 
        dx=x+fx;
        dy=y+fy;
        if (dx>=1&&dx<=n&&dy>=1&&dy<=m&&a[dx][dy]=='W')
            dfs(dx,dy);
        }
    }
}
int main()
{
    scanf("%d %d\n",&n,&m);
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
            cin>>a[i][j];
    }
    ans=0;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
        {
            if (a[i][j]=='W')
            {
                ans++;
                dfs(i,j);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

与数水坑十分类似的题目

题目链接
在这里插入图片描述
在这里插入图片描述
此题答案各位小可爱自行寻找。

6. 打死我也不说

对于给定的矩阵,请判断其中是否藏有“DSWYBS”,如果有,给出首末两个字母的下标并计算密码;如果没有,打印一行“DSWYBS”。

注意:

若藏有“DSWYBS”,则这串字母必是沿行、列或斜45度方向依次排列的。
题目保证输入的矩阵至多藏有一串“DSWYBS”。
矩阵左上角下标为(0,0)。
区分大小写。
题目保证输入的矩阵不含有类似这样的排列(即:仅有DSWYB五个字母,但是字母B与S相邻,可组成DSWYBS的排列 ) :
DSB
WY
输入格式:
第一行给出两个整数M、N(均不大于15、不小于4),接下来M行,每行有N个字母或数字,以换行结束。

输出格式:
如果输入矩阵中藏有“DSWYBS”,则输出三行,第一行和第二行分别是首字母D的下标和末字母S的下标,先行下标后列下标,以一个空格间隔。第三行给出两个字母四项下标值之和。

如果没藏有该串字母,则打印一行“DSWYBS”

输入样例1:
8 10
0x00z000d0
00aD00s000
00b0SWk000
000wcY000s
00000B0000
0000S00000
0000000000
0000000000
输出样例1:
1 3
5 4
13
输入样例2:
5 5
12345
adswa
54321
dswys
aaaaa
输出样例2:
DSWYBS

#include<stdio.h>
char arr[16][16];
int dx,dy;
int sx,sy,mx,my;
int flag=0;
 int m,n;
char ans[]="DSWYBS";
int fx[8][2]={{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
void dfs(int x,int y,int step)
{
    if(step==6)
    {
        sx=x;
        sy=y;
        flag=1;
        return;
    }
    for(int i=0;i<8;i++)
    {
       
        dx=x+fx[i][0];
        dy=y+fx[i][1];
        if(dx>=0&&dx<m&&dy>=0&&dy<n&&arr[dx][dy]==ans[step])
        {
          dfs(dx,dy,step+1);   
        }
    }
}

int main()
{
   
    scanf("%d %d",&m,&n);
    getchar();
    for(int l=0;l<m;l++)
    {
        for(int k=0;k<n;k++)
        {
            scanf("%c",&arr[l][k]);
        }
        getchar();
    }
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
    if(arr[i][j]=='D')
        dfs(i,j,1);
            if(flag)
            {
                mx=i;
                my=j;
                break;
            }
           
            }
         if(flag)
                break;
    }
    if(flag)
    {
    printf("%d %d\n",mx,my);
    printf("%d %d\n",sx,sy);
    printf("%d",mx+my+sx+sy);
    }
    else
    {
        printf("DSWYBS");
    }
    return 0
    }

7. 字母顺序归位

字符串顺序被打乱了

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int ans=1000;
string s,a="swpuacmnb";
void dfs(int deep,string p)
{
    if(deep>9)   
        return ;
    if(p==a)
    {
    ans=min(ans,deep);
    return ;
    }
    for(int i=0;i<9;i++)
    {
    if(p[i]!=a[i])
    {
        for(int j=i+1;j<9;j++)
        {
            if(p[j]==a[i])
            {
                swap(p[j],p[i]);
                dfs(deep+1,p);
                swap(p[i],p[j]);
            }
        }   
    }
    }
}
int main()
{
    cin>>s;
    dfs(0,s);
    cout<<ans;
    return 0;
}

8. 不同路径数

在这里插入图片描述
在这里插入图片描述
set+dfs:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
const int N = 10;
int n, m, k;
int g[N][N];
set<int> S;//可以保证S中的数都不同
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void dfs(int x, int y, int u, int num)
{
    if (u == k) S.insert(num);//达到k步
    else
    {
        for (int i = 0; i < 4; i ++ )
        {
            int a = x + dx[i], b = y + dy[i];
            if (a >= 0 && a < n && b >= 0 && b < m)
                dfs(a, b, u + 1, num * 10 + g[a][b]);
        }
    }
}
int main()
{
    //输入:
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < m; j ++ )
            scanf("%d", &g[i][j]);
            
    //每一个点都dfs一次
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < m; j ++ )
            dfs(i, j, 0, g[i][j]);

    printf("%d\n", S.size());
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1822847.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SSM框架的电影院售票网站

开头语&#xff1a; 你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果您对我们的电影院售票网站感兴趣或者有相关需求&#xff0c;欢迎通过文末的联系方式与我联系。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM框架 工具&#xff1a;ID…

【 EI会议 | 西南大学主办 | 往届均已实现检索】第三届神经形态计算国际会议(ICNC 2024)

第三届神经形态计算国际会议&#xff08;ICNC 2024) 2024 3rd International Conference on Neuromorphic Computing (ICNC 2024) 一、重要信息 大会官网&#xff1a;www.ic-nc.org&#xff08;点击投稿/参会/了解会议详情&#xff09; 会议时间&#xff1a;2024年12月13-15…

for 、while循环

练习1&#xff1a;输入一个数&#xff0c;判断是否是完美数 完美数&#xff1a;正序和逆序的结果一致 练习2&#xff1a; * ** *** **** 练习3&#xff1a; **** *** ** * 练习4&#xff1a;输入一个数&#xff0c;计算最大公约数&#xff0c;以及最小公倍数 练习5&#xff…

Git代码冲突原理与三路合并算法

Git代码冲突原理 Git合并文件是以行为单位进行一行一行合并的&#xff0c;但是有些时候并不是两行内容不一样Git就会报冲突&#xff0c;这是因为Git会帮助我们进行分析得出哪个结果是我们所期望的最终结果。而这个分析依据就是三路合并算法。当然&#xff0c;三路合并算法并不…

Python第二语言(十四、高阶基础)

目录 1. 闭包 1.1 使用闭包注意事项 1.2 小结 2. 装饰器&#xff1a;实际上也是一种闭包&#xff1b; 2.1 装饰器的写法&#xff08;闭包写法&#xff09; &#xff1a;基础写法&#xff0c;只是解释装饰器是怎么写的&#xff1b; 2.2 装饰器的语法糖写法&#xff1a;函数…

AMD核显推理Stable Diffusion

目标 近期&#xff0c;我开始了尝试使用Stable Diffusion进行文生图和。为此&#xff0c;我也尝试了多种在线服务&#xff0c;如WHEE。虽然在线平台能够提供不错的生成效果&#xff0c;但是生成的图片太多的话最终还是需要收费的。 因此我想尝试在本地部署SD模型进行图像生成。…

使用Leaflet库创建交互式地图:技术解析与实践

一&#xff1a;引言 在现代Web开发中&#xff0c;地图可视化已成为许多项目不可或缺的一部分。Leaflet是一个开源的JavaScript库&#xff0c;用于在Web页面上创建交互式地图。它简单易用、轻量级且高度可定制&#xff0c;使得开发者能够快速地创建出具有丰富功能的地图应用。本…

提升你的编程体验:自定义 PyCharm 背景图片

首先&#xff0c;打开 PyCharm 的设置菜单&#xff0c;点击菜单栏中的 File > Settings 来访问设置&#xff0c;也可以通过快捷键 CtrlAItS 打开设置。 然后点击Appearance & Behavior > Appearance。 找到Background image...左键双击进入。 Image:传入自己需要设置…

Unity引擎在UI上渲染粒子播放

大家好&#xff0c;我是阿赵。   在UI上面显示粒子特效&#xff0c;如果把粒子系统直接拖到Canvas里面&#xff0c;会存在很多问题&#xff0c;比如层级问题、裁剪问题等。这里分享一种用MaskableGraphic和UIVertex来显示粒子特效的方法。 一、 MaskableGraphic和UIVertex简…

数据结构和矩阵细节用法:double、cell和complex #matlab

矩阵建立 建立矩阵用[]&#xff1b; 矩阵的同一行内的元素用逗号或者空格隔开&#xff1b; 矩阵的不同行的元素用分号隔开 eg. 矩阵 A 1 2 3 4 5 6 7 8 9 在matlab中矩阵A表示为&#xff1a; clc;clear; A[1,2,3;4,5,6;7,8,9]; %或者A[1 2 3;4 5 …

SAP FI 批量显示科目余额 发生额的报表

实际界面 结果 源代码 *&---------------------------------------------------------------------* *& Report ZRPT_FICO_F01 *&---------------------------------------------------------------------* *& 20240614 批量显示余额 发生额 *&---------…

怎么批量去除EXCEL表格内时间?(已解决)

作为竞价优化师&#xff0c;经常碰到下载表格以后发现有冗余数据&#xff0c;这个时候我们该怎么快速处理呢&#xff01; 第一步&#xff0c;选择这一行数据 第二步&#xff0c;右击选择“单元格格式-日期” 第三步&#xff0c;选择日期中的2001-3-7格式&#xff0c;点击“确定…

QML学习及实战

QML学习及实战&#xff08;更多内容&#xff09; 创建项目 3. 剩下的就是一路下一步即可 添加静态资源——图片 添加之后完成之后的路径 案列 || demo 可以参考的资料&#xff1a;https://github.com/gongjianbo/MyTestCode/blob/master/README.md 1. 文本省略号 Text {wi…

RedHat9 | Mariadb数据库的配置与管理

一、实验环境 1、Mariadb数据库介绍 MariaDB数据库管理系统是一个开源的关系型数据库管理系统&#xff0c;与MySQL高度兼容&#xff0c;并提供了更多的功能和性能优化。 起源和背景 MariaDB是MySQL的一个分支&#xff0c;主要由开源社区维护。由MySQL的创始人Michael Widen…

百度OCR初探-python

百度OCR使用&#x1f680; 在项目中需要对一些资料首先进行OCR识别&#xff0c;然后对OCR之后得到的结果进行结构化分析&#xff0c;各家的都打算简单尝试一下&#xff0c;首先尝试一下百度的OCR&#xff0c;首先找到百度的OCR的官方&#xff0c;开始自己搜索然后尝试。 OCR&am…

浅谈数据管理架构 Data Fabric(数据编织)及其关键特征、落地应用

伴随着企业从数字化转型迈向更先进的数智化运营新阶段&#xff0c;对看数、用数的依赖越来越强&#xff0c;但数据的海量增长给数据管理带来一系列难题&#xff0c;如数据类型和加工链路日益复杂&#xff0c;数据存储和计算引擎更加分散&#xff0c;数据需求响应与数据质量、数…

【电机控制】FOC算法验证步骤——PWM、ADC

【电机控制】FOC算法验证步骤 文章目录 前言一、PWM——不接电机1、PWMA-H-50%2、PWMB-H-25%3、PWMC-H-0%4、PWMA-L-50%5、PWMB-L-75%6、PWMC-L-100% 二、ADC——不接电机1.电流零点稳定性、ADC读取的OFFSET2.电流钳准备3.运放电路分析1.电路OFFSET2.AOP3.采样电路的采样值范围…

kubespray离线安装k8s

kubespray离线安装k8s 系统环境 OS: Static hostname: test Icon name: computer-vm Chassis: vm Machine ID: 22349ac6f9ba406293d0541bcba7c05d Boot ID: 83bb7e5dbf27453c94ff9f1fe88d5f02 Virtualization: vmware Operating System: Ubuntu 22.04.4 LTS Kernel: Linux 5.…

哪个牌子的开放式耳机性价比高呢?五大口碑销量双佳产品汇总!

​喜欢户外活动的朋友们&#xff0c;你们都是懂得享受生活的达人吧&#xff01;想象一下&#xff0c;在户外活动时&#xff0c;如果能有一副既适合场景又提供超棒音乐体验的耳机&#xff0c;那该多完美啊&#xff01;这时候&#xff0c;开放式耳机就闪亮登场了&#xff01;它的…

JAVAEE值之网络原理(1)_用户数据报协议(UDP)、概念、特点、结构、代码实例

前言 在前两节中我们介绍了UDP数据报套接字编程&#xff0c;但是并没有对UDP进行详细介绍&#xff0c;本节中我们将会详细介绍传输层中的UDP协议。 一、什么是UDP&#xff1f; UDP工作在传输层&#xff0c;用于程序之间传输数据的。数据一般包含&#xff1a;文件类型&#xff0…