深度优先搜索

深度优先搜索

2019.11.30

深度优先搜索得关键在于解决“现在怎么做”,“下一步怎么做”跟“现在怎么做”是一样的,所以我们一般都是用for来遍历的,自己写的函数可以用递归来写。

伪代码(基本模型)

void 函数名(形参)
{
	判断边界(就相当于递归的机械条件)
	尝试每一种可能for()
	{
		继续下一步操作函数名(形参);
	}
	返回
}

盒子里放扑克牌(n的全排列)

#include<iostream>
using namespace std;
int a[10], book[10], n;//a表示结果,就是盒子里放的几号扑克牌  book数组表示牌在不在手上 0表示在手上 1反之 n表示盒子数 
void dfs(int temp)
{
	if(temp == n+1)//当temp个盒子都放完时,及循环到temp+1个盒子,但是已经没盒子可以放了 
	{
		for(int i = 1; i <= n; i++)
			cout << a[i];
		cout << endl;
		return; 
	}
	for(int i = 1; i <= n; i++)//循环所有可能 
	{
		if(book[i] == 0)//当第i号扑克牌还在手上时 
		{
			a[temp] = i;//把i号扑克牌放到第temp个盒子里 
			book[i] = 1;//标记i号扑克牌不在手上 
			dfs(temp+1);//我 调 我 自 己    进行下一步 
			book[i] = 0;//拿回放在第temp个盒子里的牌 
		}
	}
	return;
}
int main()
{
	cin >> n;
//	for(int i = 0; i < n; i++) //可以不用敲 定义全局数组系统默认数组的元素都为0
//		book[i] = 0;
	dfs(1);
	return 0;
}

XXX+XXX=XXX

要求:用1~9,并且所有数字只能用一次。
思路:(有点像枚举) 一开始从1开始循环到9,如果用到的数字就在book数组标记,顺便放到a数组里(两个数组都得按位置放),当book里所有元素加起来等于10后就可以判断XXX+XXX=XXX了。

//XXX+XXX=XXX 1~9每个数字只能用一次 
#include<iostream>
using namespace std;
int book[10], a[10], n = 0;
void f(int temp)
{
	if(temp == 10)
	{
		if(a[1]*100+a[2]*10+a[3]+a[4]*100+a[5]*10+a[6] == a[7]*100+a[8]*10+a[9])
		{
			cout << a[1] << a[2] << a[3] << "+" << a[4] << a[5] <<a[6] << "==" << a[7] << a[8] << a[9];
			cout << endl;
			n++;
		}
		return;
	}
	for(int i = 1; i <= 9; i++)
	{
		if(book[i] == 0)
		{
			a[temp] = i;
			book[i] = 1;
			f(temp+1);
			book[i] = 0;
		}
	}
	return;
}

int main()
{
	f(1);
	cout << n/2;// 为什么要/2 :因为有重复的 加号左右两边可以互相调换 
	return 0;	
} 

2019.12.01

走迷宫

题意:从某一点走出迷宫,算出最小路径,迷宫里右障碍
思路:要疯狂试下一步怎么走,而在迷宫里只能向上下左右走,所以如图,(x,y)是现在的位置,这个是核心点。
在这里插入图片描述
dfs函数中要判断是否把整个地图都走过了,还要判断是否超过了边界,以及这个位置是否为障碍或者这个位置走过了。

error:reference to ‘min’ is ambiguous
本来想定义一个min来记录最小路径,但是出现了这个错误(对“ min”的引用不明确),百度了一下发现时头文件iostream中有函数或变量重名了,把min改下名字就行了

#include<iostream> 
using namespace std;
int a[51][51], book[51][51];//a表示地图 0为空地 1为障碍   book表示这一格有没有走过 
int n, m, p, q, M = 9999;// n为地图行 m为列  p为目的行 q为目的列 M表示路径最短 
void dfs(int x, int y, int step)
{
	int tx, ty;
	int next[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};//分别向右、下、左、上走 
	if(x == p && y == q)//判断是否走完整个地图 
	{
		if(step < M)//更新最小值 
			M = step;
		return ;
	}
	for(int i = 0; i < 4; i++)
	{
		tx = x + next[i][0];
		ty = y + next[i][1];
		if(tx < 1 || ty < 1 || tx > n || ty > m)//判断是否出界 
			continue;
		if(a[tx][ty] == 0 && book[tx][ty] == 0)
		{
			book[tx][ty] = 1;//标记走过 
			dfs(tx,ty,step+1);//下一步 
			book[tx][ty] = 0;//标记没走过 
		}
	}
	return ;
}
int main()
{
	int starx, stary;
	cin >> n >> m;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			cin >> a[i][j];
	cin >> starx >> stary >> p >> q;
	book[starx][stary] = 1;
	dfs(starx, stary, 0);
	cout << M;
	return 0;
}
/*5 4
0 0 1 0
0 0 0 0
0 0 1 0
0 1 0 0
0 0 0 1
1 1 4 3*/ 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值