dfs模板

目录

总结

dfs的应用(模板)

举例:

dfs 应用实验

快排(分区交换排序)

算法描述:


总结

今天听了学长讲的东西之后自己又认真梳理了一下,并且做出了一个最简单的走迷宫题目,(虽然很简单),但是这次真的理解了。

dfs的应用(模板)

(1)走迷宫问题(结合回溯算法)

(2)检验连通性的问题(求联通分量)

举例:

1、迷宫问题

题目:

有一个n*m的迷宫,迷宫中有一些障碍,问你是否有从起点(sx,sy)到终点(fx,fy)的路线,‘&’代表可走的路,‘#’代表障碍不可通过,‘@’代表起点,‘=’代表终点,只可以上下左右的移动

4 5

@&###

#&&&#

#&&&&

##&&=

思想:

有个模拟上下左右移动的数组s[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

有个存放地图信息的数组mp,和标记走没走过的数组vis,vis在搜索过程中可以防止来回移动造成死循环

而且在搜完一种状态后,要回溯,不然搜索的初始条件就发生了改变,结果可能会不对

从起点开始上下左右的搜

 dfs函数:

 2、连通块问题

题目:

有个n*m的01矩阵,矩阵中只有0和1两种数字,如果一个0上下左右有0则把这些0视为同一个块,问你这个矩阵中有多少这样的块

输入

4 5

0 0 0 1 1

1 1 1 0 0

1 1 1 0 0

1 0 1 0 1

输出    3

思路:

我们可以遍历这个矩阵,当遍历到0时,我们可以从这个坐标开始上下左右搜索,把搜索到的0全部赋为1,应为这些0都是同属于一个块的,当搜完时,块的数量+1

dfs函数: 

 

dfs 应用实验

题目:

给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

输入:

第一行N、M和T,N为行,M为列,T为障碍总数。第二行起点坐标SX,SY,终点坐标FX,FY。接下来T行,每行为障碍点的坐标。

输出:

给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。

样例:

:输入 #1

2 2 1
1 1 2 2
1 2

输出 #1

1

代码实现:

#include<stdio.h>
int sum=0;//计数 
int n,m,t;
int sx,sy,fx,fy;
int a[10][10]={0},b[10][10]={0};//数组a记录图,数组b记录走没走过 
int s[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//向上下左右走 
void dfs(int x,int y)//深搜函数 
{
	if(x==fx&&y==fy)//走到终点 
		sum++;
	int xx,yy;
	for(int i=0;i<4;i++)//判断四种路径 
	{
		xx=x+s[i][0];
		yy=y+s[i][1];
		if(xx<1||yy<1||xx>n||yy>m||a[xx][yy]==1||b[xx][yy]==1)
			continue;//边界或者障碍点或者走过 
		b[xx][yy]=1;//走过 
		dfs(xx,yy);//继续搜索 
		b[xx][yy]=0;//回溯	
	}
}
int main()
{
	cin>>n>>m>>t;
	cin>>sx>>sy>>fx>>fy;
	while(t--)
	{
		int tx,ty;
		cin>>tx>>ty;
		a[tx][ty]=1;
	}
	b[sx][sy]=1;//标记起点 
	dfs(sx,sy);
	cout<<sum; 
	return 0;	
} 

快排(分区交换排序)


算法描述:

给出一个temp值(默认为数组第一个位置上的数),从数组开头 i 开始找大于temp的数,数组末端 j 开始找小于temp的数,找到之后两位置上的数进行交换,然后(i++,j--)继续找后面小于temp,前面大于temp的数进行交换,直到i=j;把基准点移到i位置,对基准点左右子序列分别进行递归,以此类推,最后得到一个排序好的数组。🐏🐏🐑

图片模拟:

 代码实现:


#include<stdio.h>
int a[100],n;
void fun(int left,int right)
{
	int i,j,t,temp;
	if(left>right)
		return;
	temp=a[left];
	i=left;j=right;
	while(i!=j)
	{
		while(a[j]>=temp&&i<j)
			j--;
		while(a[i]<=temp&&i<j)
			i++;
		if(i<j)
		{
			t=a[i];
			a[i]=a[j];
			a[j]=t;
		}
	}
	a[left]=a[i];
	a[i]=temp;
	fun(left,i-1);
	fun(i+1,right);
} 
int main()
{
	int t;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	fun(1,n);
	for(int i=1;i<=n;i++)
		printf("%d",a[i]);
	getchar();getchar();
	return 0;
		
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值