dfs bfs 从入门到人坑完整版

dfs:为深度优先搜索

思路:

一直往下找,不撞南墙不回头。
暴力把所有路径搜索出来,运用回溯,搜下一个位置。(有时候不需要回溯)

统一伪代码(为常见问题的)

到达(a点)
{
	for(从a点出发能去的相邻的点q)
	{
	if(没有来过q}
	{
		记录q点到过了
		到达(q点)使用递归
		
	}
	返回a点前一步 
}

回溯操作

使用情况:每一次的数据,都携带前面步骤的数据。所以前面的数据会影响后面的数据,就要用回溯。
只需要在源代码中加一步:

到达(a点)
{
	for(从a点出发能去的相邻的点q)
	{
	if(没有来过q}
	{
		记录q点到过了
		到达(q点)使用递归
		//加一步:
		取消记录q点到过//回溯操作
	}
	返回a点前一步 
}

当每一次尝试都有独特数据,并不影响其他尝试,就不需要回溯。

剪枝操作

限制迭代次数,遇到非法情况直接退出
当迭代深度过大,可设置自动退出函数,也叫一种剪枝

dfs搜索记忆化

记忆化的意思是:访问某个数据时,能直接给出值,而不需重复递归。
使用了记忆化搜索,就不需要标记了,且具有返回值。而且也能使用dp动态规划。
例如:
斐波那契数列用普通递归:
每次搜索都是指数级别,时间复杂度是不可取的

public static int dfs (int n)
	{
		if(n==1) return 1;
		else {
			return dfs(n-1)+dfs(n-2);
		}
	}

但是用dfs搜索记忆化:
只需要在搜索时,将值放进一个数组中,就可以避免重复递归(有点像预处理或者dp)
就可大大降低时间复杂度

public static int dfs (int n)
	{
		if(n==1) 
			{
			x[n]=1;//记忆化搜索
			return 1;
			}
		else {
			if(x[n]!=0) return x[n];
			x[n]=dfs(n-1)+dfs(n-2);//记忆化搜索
			return dfs(n-1)+dfs(n-2);
		}
	}

dfs的基础应用:

图的遍历
枚举问题:一般就是利用回溯的dfs,数据范围较小排列组合的枚举
二维平面问题

例题:

1,T160513 E - 运气

import java.util.Scanner;

//2021年3月17日下午7:01:34
//writer:apple
public class Main {
	static long n;
	static long k;
	static long  maxx=(int) (1e9+7);
	static long ans;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner=new Scanner(System.in);
		n=scanner.nextInt();k=scanner.nextInt();
		for(int i=1;i<=6;i++)
		{
			dfs(i,1);
		}
		System.out.println(ans%maxx);

	}
	
	public static void dfs(long x,long step)
	{
		if(step==n)
		{
			if(x%k==0) ans++;
			return ;
		}
			for(int i=1;i<=6;i++)
			{
					dfs(x*10+i,step+1);
			}
		
	}

}

2,全排列:

package tu;

import java.util.Arrays;
import java.util.Scanner;

//2021年3月17日上午8:27:39
//writer:apple
public class tu1_1 {

	static int vis[];
	static int ans[];
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner=new Scanner(System.in);
		int n=scanner.nextInt();
		int x[]=new int[n];
		vis=new int[n];
		ans=new int[n];
		for(int i=0;i<n;i++)
		{
			x[i]=scanner.nextInt();
		}
		Arrays.sort(x);
		dfs(x,0);
	}
	
	public static void dfs(int a[],int step)
	{
		if(step==a.length)
		{
			for (int i = 0; i <step; i++) {
				System.out.print(ans[i]+" ");
			}
			System.out.println();
		}
		else {
			for(int i=0;i<a.length;i++)
			{
				if(vis[i]==1) continue;
				vis[i]=1;
				ans[step]=a[i];
				dfs(a,step+1);
				vis[i]=0;
			}
		}
	}
}

3 八皇后问题:皇后会攻击一行,一列,两对角线

package tu;
//2021年3月17日上午9:14:24
//writer:apple
public class eightqueen_2 {

		// TODO Auto-generated method stub
		static int ans[][]=new int[9][9];//ans[i][j] 为第i个皇后在第j列   同时用来记录标记
		static int cout=0;
		public static void main(String[] args) {
			// TODO Auto-generated method stub
			dfs(1);

		}

		public static void dfs(int step)//代表第i个皇后 也代表第i行
		{
			if(step==9)
			{
				cout++;
//				show();
				System.out.print(cout+" ");
				for(int i=1;i<=8;i++)
				{
					for(int j=1;j<=8;j++)
					{
						if(ans[i][j]==1)
						{
							System.out.printf("(%d,%d)",i,j);
						}
					}
				}
				System.out.println();
			}
			for(int j=1;j<=8;j++)//1-8列
			{
				if(!checklegal(step, j))   continue;
				ans[step][j]=1;
				dfs(step+1);
				ans[step][j]=0;
			}
		}
		public static boolean checklegal(int step,int j)
		{
			for(int i=1;i<=step;i++)
			{
				for(int k=1;k<=8;k++)//列
				{
					if(ans[i][j]==1) return false;//列相同
					if((step-i==j-k||step-i==k-j)&&ans[i][k]==1) return false;//对角线相同
				}
			}
			return true;
		}
	}

4, P1605 迷宫

import java.util.Scanner;

//2021年3月17日上午9:28:51
//writer:apple
public class migong {

	static int n;
	static int m;
	static int t;
	static int map[][];//0可过 1为障碍
	static int vis[][];
	static int x0,y0;
	static int x1,y1;
	static int ans;
	static int d[][]= {{1,0},{0,1},{-1,0},{0,-1}};
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner=new Scanner(System.in);
		n=scanner.nextInt();m=scanner.nextInt();t=scanner.nextInt();
		map=new int[n+1][m+1];vis=new int[n+1][m+1];
		x0=scanner.nextInt();y0=scanner.nextInt();
		x1=scanner.nextInt();y1=scanner.nextInt();
		while(t-->0)
		{
			int x=scanner.nextInt();int y=scanner.nextInt();
			map[x][y]=1;
		}
		vis[x0][y0]=1;
		dfs(x0,y0);
		System.out.println(ans);
	}
	
	public static void dfs(int x,int y)
	{
		if(x==x1&&y==y1)
		{
			ans++;
		}
		for(int i=0;i<4;i++ )
		{
			int nextx=x+d[i][0];int nexty=y+d[i][1];
			if(nextx>n||nextx<1) continue;if(nexty>m||nexty<1) continue;//越界
			if(map[nextx][nexty]!=1&&vis[nextx][nexty]==0)//无障碍  没走过
			{
				vis[nextx][nexty]=1;
				dfs(nextx,nexty);
				vis[nextx][nexty]=0;
			}
		}		
	}
}

5,对称迷宫 25’

描述
wlxsq有一个N*NN∗N的网格迷宫,每一个网格都有一个字母编号。

他要从左上角(1,1)(1,1)出发,走到右下角(n,n)(n,n),由于wlxsq很懒,所以他每次只会往右或者往下走一格。

由于最后到终点的路径方案太多太多了,所以wlxsq想让你计算出所有不同的对称的路径个数。

例如:N = 3N=3

ABA

BBB

ABA

对称路径6条:有ABABA(2条)、ABBBA(4条)

不同的对称路径有: 有ABABA、ABBBA

输入
第一行输入一个数NN,表示迷宫的大小。

接下来输入N*NN∗N的字母迷宫

输出
输出对称路径的数量

样例
输入复制
3
ABA
BBB
ABA

输出复制
2
提示
【评测用例规模与约定】

对于40%40%的数据,2<=N<=112<=N<=11

对于100%100%的数据,2<=N<=182<=N<=18

#include<iostream>
#include<cstring>
#include<vector>
#include<set>
#include<map>
using namespace std;

int n;
int lang;
int ans=0;

char a[20][20];
vector <string> b;
vector<string>b2;
map<string,int> ha;
set<string> path[20];
void dfs1(int x,int y,string t)
{
	
	
	t+=a[x][y];
	
	if(x+y==n-1)
	{
		path[x].insert(t);
		ha[t]=1;
		return ;
	}
	dfs1(x+1,y,t);
	dfs1(x,y+1,t);
}
void dfs2(int z,int q,string g) 
{
	g+=a[z][q];
	if(z+q==n-1)
	{
		if(path[z].count(g)&&ha[g])
		{
			ans++;
			ha[g]=0;
		}
		return ;
	}
	dfs2(z-1,q,g);
	dfs2(z,q-1,g);
}
int main()
{
	ios::sync_with_stdio(false);		
	cin>>n;
	for(int i=0;i<n;i++)	
	{
		cin>>a[i];
	}
	lang=n*2-1;
	dfs1(0,0,"");
	dfs2(n-1,n-1,"");
	cout<<ans;
 	return 0;
}

6, P1434 [SHOI2002]滑雪.

题解:使用记忆化搜索,dfs有返回值,减小递归深度。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

//2021年3月17日上午10:34:58
//writer:apple
public class Main {

	static int n,m;
	static int map[][];
	static int maxlen;
	static int d[][];//从i,j开始的长度
	static int direction[][]= {{1,0},{0,1},{-1,0},{0,-1}};
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String t1[]=br.readLine().split(" ");
		n=Integer.parseInt(t1[0]);m=Integer.parseInt(t1[1]);
		map=new int[n+1][m+1];
		d=new int[n+1][m+1];
		for(int i=1;i<=n;i++)
		{
			String t[]=br.readLine().split(" ");
			for(int j=0;j<t.length;j++)
			{
				d[i][j+1]=1;
				map[i][j+1]=Integer.parseInt(t[j]);
			}
		}
		
		for(int i=1;i<=n;i++ )
		{
			for(int j=1;j<=n;j++)
			{
				dfs(i,j);
			}
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
//				d[i][j]=dfs(i,j);
				maxlen=Math.max(maxlen, d[i][j]);
			}
		}
		System.out.println(maxlen);

	}
	
	public static void dfs(int x,int y)
	{
		for(int i=0;i<4;i++)
		{
			int newx=x+direction[i][0];int newy=y+direction[i][1];
			if(newx>n||newx<1) continue; if(newy>n||newy<1) continue;
			if(map[newx][newy]>map[x][y]&&d[newx][newy]<d[x][y]+1)
			{
				
				d[newx][newy]=d[x][y]+1;//记忆化
				dfs(newx,newy);
			}
			
		}
	}

}
package tu;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

//2021年3月17日上午9:53:27
//writer:apple
public class skiing {

	static int n,m;
	static int map[][];
	static int vis[][];
	static int maxlen;
	static int d[][];//从i,j开始的长度
	static int direction[][]= {{1,0},{0,1},{-1,0},{0,-1}};
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		Scanner scanner=new Scanner(System.in);
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String t1[]=br.readLine().split(" ");
		n=Integer.parseInt(t1[0]);m=Integer.parseInt(t1[1]);
		map=new int[n+1][m+1];vis=new int[n+1][m+1];
		d=new int[n+1][m+1];
		for(int i=1;i<=n;i++)
		{
			String t[]=br.readLine().split(" ");
			for(int j=0;j<t.length;j++)
			{
				map[i][j+1]=Integer.parseInt(t[j]);
			}
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
//				d[i][j]=dfs(i,j);
				d[i][j]=dfs(i, j);
			}
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
//				d[i][j]=dfs(i,j);
				maxlen=Math.max(maxlen, d[i][j]);
			}
		}
		System.out.println(maxlen);
	}
	public static int dfs(int x,int y)
	{
		if(d[x][y]!=0) return d[x][y];//因为已经记忆化,可以直接返回数据值
		d[x][y]=1;//自己本身,这些
		for(int i=0;i<4;i++)
		{
			int newx=x+direction[i][0];int newy=y+direction[i][1];
			if(newx>n||newx<1) continue; if(newy>n||newy<1) continue;
			if(map[newx][newy]<map[x][y])
			{			
				d[x][y]=Math.max(d[x][y], dfs(newx,newy)+1);//记忆化
			}
			
		}
		return d[x][y];
	}
}

7 P3916 图的遍历

solution:
反向dfs+记忆化搜索,运用链表

package tu;

import java.util.ArrayList;
import java.util.Scanner;

//2021年3月18日上午9:28:00
//writer:apple
public class tubianli {
	static int n;
	static int m;
	static int ans[];
	static int cnt=0;//写链表
	static ArrayList<Integer> a[];
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner=new Scanner(System.in);
		n=scanner.nextInt();m=scanner.nextInt();
		ans=new int[n+1];
		a=new ArrayList[n+1];
		for(int i=0;i<=n;i++) a[i]=new ArrayList<>();
		
		
		for(int i=1;i<=m;i++)
		{
			int star=scanner.nextInt();int end=scanner.nextInt();
			a[end].add(star);
		}
		for(int i=n;i>=1;i--)
		{
+			dfs(i,i);
		}
		for(int i=1;i<=n;i++)
		{
			System.out.print(ans[i]+" ");
		}
	}
	
	public static void dfs(int x,int max)
	{		
		if(ans[x]==0)
		{
			ans[x]=max;
		}
		else {
			return;
		}
		for(int i=0;i<a[x].size();i++)
		{
				dfs(a[x].get(i),max);
		}
	}
}

8,POJ1321

import java.util.Scanner;

//2021年4月13日下午7:01:45
//writer:apple
public class Main{

	static int n;
	static int k;
	static int map[][];
	static boolean vis[];
	static int ans;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner s=new Scanner(System.in);
		while(true) {
			n=s.nextInt();k=s.nextInt();
			if(n==-1&&k==-1) break;
			map=new int[n][n];
			vis=new boolean [n];
				for(int j=0;j<n;j++)
				{
					vis[j]=false;
				}
			String h="";
			for(int i=0;i<n;i++)
			{
				h=s.next();
				for(int j=0;j<h.length();j++)
				{
					if(h.charAt(j)=='.')
					{
						map[i][j]=0;
					}
					else map[i][j]=1;
				}
			}
			ans=0;
			dfs(0,0);
			System.out.println(ans);
		}
	}
	private static void dfs(int x,int steps) {
		// TODO Auto-generated method stub
		if(steps==k)
		{
			ans++;return;
		}
		for(int i=x;i<n;i++ )
		{
			for(int j=0;j<n;j++)
			{
				if(map[i][j]==1&&!vis[j])
				{
						vis[j]=true;
						dfs(i+1,steps+1);
						vis[j]=false;
				}
			}
		}
		
	}
	
}

9,L3-001 凑零钱 (30 分)(学到很多)

在这里插入图片描述

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

const double eps = 1e-8; //const只是用来定义常量,常量在代码中一直存在,但define是预处理功能,有本质区别
const int maxx = 0x7f7f7f7f;//0x7f7f7f7f表示数据的无穷大
//常用的浮点数比较宏定义:
#define Equ(a,b) ((fabs((a)-(b)))<(eps)) //等于
#define More(a,b) (((a)-(b))>(esp)) //大于
#define Less(a,b) (((a)-(b))<(-esp))//小于
#define MoreEqu(a,b) (((a)-(b))>(-esp))//大于等于
#define LessEqu(a,b) (((a)-(b))<(esp))//小于等于
#define  MAX( x, y )  ( ((x) > (y)) ? (x) : (y) )//
//使用了algorithm头文件就可以直接使用max函数;
#define  MIN( x, y )  ( ((x) < (y)) ? (x) : (y) )
#define ll long long
#define PI 3.1415926
#define eps 1e-8
#define Conn(x,y) x##y;
int n;
int sum;
int coin[20000];
int reasum[20000];
bool hassee=false;
void dfs(int x,int num,int val)
{
	if(hassee||x>n+1||val>sum) return;
	if(val+reasum[x]<sum) return ;
	if(val==sum)
	{
		hassee=true;
		cout<<coin[vis[1]];
		for(int i=2;i<num;i++)
		{
			cout<<" "<<coin[vis[i]];
		}
		return ;
	}
	vis[num]=x;
	dfs(x+1,num+1,val+coin[x]);
	dfs(x+1,num,val);
}
int main()
{
	cin>>n>>sum;
	for(int i=1;i<=n;i++)
	{
		cin>>coin[i];
	}
	sort(coin+1,coin+n+1);
	for(int i=n;i>=1;i--)
	{
		reasum[i]=reasum[i+1]+coin[i];
	}
	dfs(1,1,0);
	if(hassee==false)
	{
		cout<<"No Solution";
	}
	return 0;
}

bfs:为广度优先搜索

一般操作:

使用的是循环访问,而不是递归访问

  • 运用FIFO队列,queue存储数据
  • 循环操作:该点入队,相连的所有点入队
  • 结束条件:队列为空

统一伪代码(为常见问题的)

起点放入到队列
while(队列不为空)
{
	取出队列一点a
	弹出a
	for(遍历a点所有相连的点)
	{
		if(没访问过的点)//如果是图的话,就一定要标记,避免重复
						//如果是树的话,可以不用 标记
		{
				放入队列
				标记访问过
		}
	}
}

比如
//进行广度搜索,因为题目有字典序规则,所以我们要先从终点开始,遍历一遍起点 得到最短步数。 然后在根据字典从小到大{‘D’,‘L’,‘R’,‘U’}搜索最小字典序

LinkedList<Integer> x=new LinkedList<Integer>();//做为队列,先进先出
x.add(n*m);
map[30][50]=1;
while(x.isEmpty()==false)//为空说明到头了
{
	int t=x.poll();//返回头结点并pop
	int oldx;int oldy;
	if(t%m==0) {
		oldx=t/m;oldy=(t-1)%m+1;
	}
	else {
		oldx=t/m+1;oldy=(t-1)%m+1;
	}
	
	for(int i=0;i<=3;i++)//这个时候先上,先下 都无所谓,后面最小字典序才需要确定
	{
		int newx=oldx+d[i][0];int newy=oldy+d[i][1];
		if((newx>=1&&newx<=30)&&(newy>=1&&newy<=50)&&(map[newx][newy]==0)&&(b[newx][newy]==0))
		{
				x.add((newx-1)*m+newy);
				map[newx][newy]=map[oldx][oldy]+1;
		}
		if(newx==30&&newy==50)
		{
			break;
		}
	}
}

7,POJ 1321

package tu;

import java.util.Scanner;

//2021年3月18日下午8:37:57
//writer:apple
public class qipan_2 {
	static int n;//n*n
	static int k;//k个棋子
//	static ArrayList<Integer> map[];//棋盘  0表示#可以放 1表示障碍物
	static int map[][];
	static int vis[];
	static int ans;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner=new Scanner(System.in);
		while(true) {
			n=scanner.nextInt();k=scanner.nextInt();
			if(n==-1&&k==-1) break;
			map=new int[n+1][n+1];
			vis=new int[n+1];
			for(int i=0;i<n;i++)
			{
				String t=scanner.next();
				for(int j=0;j<n;j++)
				{
					if(t.charAt(j)=='#') map[i+1][j+1]=0;
					else map[i+1][j+1]=1;
				}
			}
			ans=0;
			dfs(1,0);
			System.out.println(ans);
		}
		
		
	}
	
	public static void dfs(int x,int step)//
	{
		if(step==k)
		{
			ans++;return;
		}
		for(int i=x;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(map[i][j]==0&&vis[j]==0)
				{
					vis[j]=1;
					dfs(i+1,step+1);
					vis[j]=0;
				}
			}
		}
	}
}

例题:

1,题目忘了

下图给出了一个迷宫的平面图,其中标记为1 的为障碍,标记为0 的为可
以通行的地方。

010000
000100
001001
110000

迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这
个它的上、下、左、右四个方向之一。
对于上面的迷宫,从入口开始,可以按DRRURRDDDR 的顺序通过迷宫,
一共10 步。其中D、U、L、R 分别表示向下、向上、向左、向右走。

对于下面这个更复杂的迷宫(30 行50 列),请找出一种通过迷宫的方式,
其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。
请注意在字典序中D<L<R<U。

01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个字符串,包含四种字母D、U、L、R,在提交答案时只填写这个字符串,填写多余的内容将无法得分。

解析都在代码里

ackage lanqiaobei10;

import java.util.LinkedList;

//2021年3月13日上午12:07:46
//writer:apple
public class l5_true {

	static int d[][]= {{1,0},{0,-1},{0,1},{-1,0}};
	static int n=30;static int m=50;
	static char dzi[]={'D','L','R','U'};
	static int b[][]=new int[31][51];
	static int map[][]=new int[31][51];//表示广搜步骤
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String a="01010101001011001001010110010110100100001000101010"+
				"00001000100000101010010000100000001001100110100101"+
				"01111011010010001000001101001011100011000000010000"+
				"01000000001010100011010000101000001010101011001011"+
				"00011111000000101000010010100010100000101100000000"+
				"11001000110101000010101100011010011010101011110111"+
				"00011011010101001001001010000001000101001110000000"+
				"10100000101000100110101010111110011000010000111010"+
				"00111000001010100001100010000001000101001100001001"+
				"11000110100001110010001001010101010101010001101000"+
				"00010000100100000101001010101110100010101010000101"+
				 "11100100101001001000010000010101010100100100010100"+
				"00000010000000101011001111010001100000101010100011"+
				 "10101010011100001000011000010110011110110100001000"+
				"10101010100001101010100101000010100000111011101001"+
				 "10000000101100010000101100101101001011100000000100"+
				"10101001000000010100100001000100000100011110101001"+
				 "00101001010101101001010100011010101101110000110101"+
				 "11001010000100001100000010100101000001000111000010"+
				 "00001000110000110101101000000100101001001000011101"+
				 "10100101000101000000001110110010110101101010100001"+
				 "00101000010000110101010000100010001001000100010101"+
				"10100001000110010001000010101001010101011111010010"+
				 "00000100101000000110010100101001000001000000000010"+
				 "11010000001001110111001001000011101001011011101000"+
				"00000110100010001000100000001000011101000000110011"+
				 "10101000101000100010001111100010101001010000001000"+
				"10000010100101001010110000000100101010001011101000"+
				 "00111100001000010000000110111000000001000000001011"+
				 "10000001100111010111010001000110111010101101111000";
		for(int i=1;i<=30;i++)
		{
			for(int j=1;j<=50;j++)
			{
				b[i][j]=a.charAt((i-1)*50+j-1)-'0';
			}
		}
		
		//进行广度搜索,因为题目有字典序规则,所以我们要先从终点开始,遍历一遍起点 得到最短步数。 然后在根据字典从小到大{'D','L','R','U'}搜索最小字典序
		LinkedList<Integer> x=new LinkedList<Integer>();//做为队列,先进先出
		x.add(n*m);
		map[30][50]=1;
		while(x.isEmpty()==false)//为空说明到头了
		{
			int t=x.poll();//返回头结点并pop
			int oldx;int oldy;
			if(t%m==0) {
				oldx=t/m;oldy=(t-1)%m+1;
			}
			else {
				oldx=t/m+1;oldy=(t-1)%m+1;
			}
			
			for(int i=0;i<=3;i++)//这个时候先上,先下 都无所谓,后面最小字典序才需要确定
			{
				int newx=oldx+d[i][0];int newy=oldy+d[i][1];
				if((newx>=1&&newx<=30)&&(newy>=1&&newy<=50)&&(map[newx][newy]==0)&&(b[newx][newy]==0))
				{
						x.add((newx-1)*m+newy);
						map[newx][newy]=map[oldx][oldy]+1;
				}
				if(newx==30&&newy==50)
				{
					break;
				}
			}
		}
		String ans="";
		//以上步骤已经确定了最短步数,以下要确定最小序列
		int xx=1;int yy=1;
		while(true)
		{
			for(int i=0;i<=3;i++)
			{
				int newx=xx+d[i][0];int newy=yy+d[i][1];
				if(newx>=1&&newx<=30&&newy>=1&&newy<=50&&b[newx][newy]==0)
				{
					if(map[newx][newy]==map[xx][yy]-1)//为同一条路径
					{
						ans+=dzi[i];
						xx=newx;yy=newy;
						break;
					}
				}
			}
			if(xx==30&&yy==50) break;
		}
		System.out.println(ans);
	}
}

2,P1443 马的遍历

package tu;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Scanner;

//2021年3月17日下午7:46:25
//writer:apple
public class bfshouse {
	static int n;
	static int m;
	static int sx;
	static int sy;
	static int map[][];
	static int d[][]= {{2,1},{1,2},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}};
	static int vis[][];
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner=new Scanner(System.in);
		n=scanner.nextInt();m=scanner.nextInt();sx=scanner.nextInt();sy=scanner.nextInt();
		map=new int[n+1][m+1];
		vis=new int[n+1][m+1];
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				map[i][j]=-1;
			}
		}
		vis[sx][sy]=1;
		map[sx][sy]=0;
		LinkedList<Integer> a=new LinkedList<>();//队列
		a.add(sx*500+sy);
		while(!a.isEmpty())
		{
			int start=a.poll();//头结点
			int x;int y;
			if(start%500==0)
			{
				x=start/500;y=(start-1)%500+1;
			}
			else {
				x=start/500;y=start%500;
			}
			for(int i=0;i<8;i++)
			{
					int nx=x+d[i][0];int ny=y+d[i][1];
					if(nx>n||nx<1) continue;if(ny>m||ny<1) continue;
					if(vis[nx][ny]==1) continue;
					a.add(nx*500+ny);
					map[nx][ny]=map[x][y]+1;
					vis[nx][ny]=1;
			}
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				System.out.printf("%-5d",map[i][j]);
			}
			System.out.println();
		}
	}
}

3 POJ3278

package 搜索;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

//2021年4月13日下午8:46:13
//writer:apple
public class a3 {

	static int n;
	static int k;
	static int ans[]=new int[100005];
	static boolean vis[]=new boolean[100005];
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner s=new Scanner(System.in);
		n=s.nextInt();k=s.nextInt();
		Queue<Integer> q=new LinkedList();
		q.offer(n);
		while(!q.isEmpty())
		{
			int od=q.poll();
			if(od==k) break;
			for(int i=0;i<3;i++)
			{
				int newd=0;
				if(i==0)
				{
					newd=od+1;
				}
				if(i==1)
				{
					newd=od-1;
				}
				if(i==2)
				{
					newd=od*2;
				}
				if(newd>=0&&newd<=100000&&!vis[newd])
				{
					vis[newd]=true;
					ans[newd]=ans[od]+1;
					q.offer(newd);
				}
			}
		}
		System.out.println(ans[k]);
	}

}

4 POJ2251

package 搜索;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

//2021年4月13日下午7:50:04
//writer:apple
public class a2 {

	static char m[][][];
	static int step[][][];
	static boolean vis[][][];
	static int a,b,c;
	static int si,sj,sk;
	static int ei,ej,ek;
	static int minlen;
	//d[][]={{},{}{}{}};
	static int d[][]= {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
	static class p
	{
		int x,y,z;
		public p(int xx,int yy,int zz)
		{
			x=xx;y=yy;z=zz;
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner s=new Scanner(System.in);
		while(true)
		{
			a=s.nextInt();b=s.nextInt();c=s.nextInt();
			if(a==0&&b==0&&c==0) break;
			step=new int[a][b][c];
			m=new char [a][b][c];
			vis=new boolean[a][b][c];
			minlen=0;
			for(int i=0;i<a;i++)
			{
				for(int j=0;j<b;j++)
				{
					m[i][j]=s.next().toCharArray();
					for(int k=0;k<c;k++)
					{
						step[i][j][k]=0;
						vis[i][j][k]=false;
						if(m[i][j][k]=='S')
						{
							si=i;sj=j;sk=k;
						}if(m[i][j][k]=='E')
						{
							ei=i;ej=j;ek=k;
						}
					}
				}
			}
			vis[si][sj][sk]=true;
//			bfs(si,sj,sk);
			p p1=new p(si,sj,sk);
			Queue<p> l=new LinkedList<p>();
			l.add(p1);
			int len=0;
			boolean f=false;
			while(!l.isEmpty())
			{
				p pt=l.poll();
				if(m[pt.x][pt.y][pt.z]=='E')
				{
					break;
				}
				for(int i=0;i<6;i++)
				{
					int nx=pt.x+d[i][0];int ny=pt.y+d[i][1];int nz=pt.z+d[i][2];
					if(nx>=a||nx<0||ny>=b||ny<0||nz>=c||nz<0) continue;
					if(m[nx][ny][nz]!='#'&&!vis[nx][ny][nz])
					{
						vis[nx][ny][nz]=true;
						step[nx][ny][nz]=step[pt.x][pt.y][pt.z]+1;
						l.add(new p(nx,ny,nz));
					}
				}
				if(f) break;
			}
			if(step[ei][ej][ek]!=0)
			System.out.printf("Escaped in %d minute(s).\n",step[ei][ej][ek]);
			else System.out.println("Trapped!");
		}
	}
	private static void bfs(int si2, int sj2, int sk2) {
		// TODO Auto-generated method stub
		
	}
}

5,POJ1426:

package 搜索;

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

//2021年4月13日下午11:28:49
//writer:apple
public class a5 {

	static int n;
	static String ans;
	static boolean vis[];
	static class node
	{
		int mod;
		String m;
		public node(int mo,String mm)
		{
			mod=mo;m=mm;
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner s=new Scanner(System.in);
		while(true)
		{
			n=s.nextInt();
			vis=new boolean[2000];
			if(n==0) break;
			//一定要用bfs 找到一个答案就行
			//用dfs 可能会一直深下去时间复杂度保障不了
			LinkedList<node> l=new LinkedList();
			if(1==n) System.out.println(1);
			else {
				String ans="";
				l.add(new node(1,"1"));
				vis[1]=true;
				while(true)
				{
					node x=l.poll();
					if(x.mod==0) 
					{
						ans=x.m;
						break;
					}
					if(!vis[x.mod*10])
					{
						l.add(new node((x.mod*10)%n,x.m+"0"));
						vis[x.mod*10]=true;
					}
					if(!vis[x.mod*10+1])
					{
						l.add(new node((x.mod*10+1)%n,x.m+"1"));
						vis[x.mod*10]=true;
					}
				}
				System.out.println(ans);
			}
		}
	}
}

dfs和bfs的区分:

dfs:一往无前,递归实现(栈实现),传参很重要
bfs:先近后远,队列实现。传参不重要。循环操作
有时候两个都可以用

dfs应用比较广泛,用起来比较简单。
适合搜索全部的解,在记录路径的时候回简单一点。

bfs比较适合用来搜索最短路劲。比如求最小步数的解,走出迷宫最短路等。因为bfs搜索过程中遇到的第一个解一定是离起点位置最近的(所以路径最小),所以遇到的第一个解,一定就是最优解,此时,搜索可以停止。
而如果用dfs搜索,会花费更多时间,而且找到了一个解,也不一定是最优解,会更麻烦

其他知识点

判断某一点是否在环内:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值