深搜(DFS):八皇后 & 广搜(BFS):奇怪的电梯

目录

1.概念

2.DFS->八皇后

3.BFS->奇怪的电梯


1.概念

深度优先搜索(DFS),一条路走到黑,回溯,遍历所有节点

广度优先搜索(BFS),层层递进,遍历所有节点

深搜和广搜可以提高枚举的效率,是我们解决问题的重要工具

2.DFS->八皇后

问题描述:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。著名数学家高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。今天,我们可以用计算机来AC这个高斯回答错误的问题。

我们可以进行一下模拟,例如现在将前三行棋子的位置输出,并输出最终结果数。可以定义一个二维数组表示棋盘,不过显然那样会增加时间复杂度,不妨直接开一个一维数组a[i]=j表示第i行皇后放在第j列上,用三个b数组判断皇后是否可以放置,然后就可以利用DFS来解决这道题目了。

代码:

#include <iostream>
using namespace std;
//DFS算法 八皇后

#define maxn 100
int a[maxn], n, ans = 0;
int b1[maxn], b2[maxn], b3[maxn];
//b1记录第i列,b2记录x+y=i斜列,b3记录x-y+15=i斜列 ->是否可放

void dfs(int x)//第x行皇后放哪
{
	if (x > n)
	{
		ans++;
		if (ans <= 3)//输出了前三种,也可以输出所有种情况
		{
			for (int i = 1; i <= n; i++)
				cout << a[i] << " ";
			cout << endl;
		}
		return;
	}

	for(int i=1;i<=n;i++)
		if (b1[i] == 0 && b2[x + i] == 0 && b3[x - i + 15] == 0)//可放置
		{
			a[x] = i;//第x行皇后放在第i列上
			b1[i] = 1;
			b2[x + i] = 1;
			b3[x - i + 15] = 1;
			dfs(x + 1);//递归下一行
			b1[i] = 0; b2[x + i] = 0; b3[x - i + 15] = 0;//回溯
		}
}

int main()
{
	cin >> n;
	dfs(1);
	cout << ans;
	return 0;
}

也可以将所有可能的情况打表输出:

#include<iostream>
//这段代码时间复杂度有点高qwq

using namespace std;

int f[16][16],cnt=0;
int n;

void print()
{
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
			cout << f[i][j] << " ";
		cout << endl;
	}
	cout << endl;
}

bool check(int x,int y)
{
	for (int i = 1; i <= n; i++)
		if (f[i][y] == 1)
			return false;
	for(int i=1;i<=n;i++)
		for (int j = 1; j <= n; j++)
		{
			if (f[i][j] == 1 && (x - y == i - j || x + y == i + j))
				return false;
		}
	return true;
}

void dfs(int row)
{
	if (row == n + 1)
	{
		cnt++;
		print();
		return;
	}
	for(int j=1;j<=n;j++)
	if (check(row,j))
	{
		f[row][j] = 1;
		dfs(row + 1);
		f[row][j] = 0;
	}
}

int main()
{
	
	cin >> n;
	dfs(1);
	cout << cnt<<endl;
}

3.BFS->奇怪的电梯

问题描述:有一天桐桐做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1≤i≤N)上有一个数字K;(0≤Ki≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki (K1=3,K2=3,…),从一楼开始。在一楼,按“上,”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?

对于BFS,我们可以借助先进先出的队列来完成。

代码:

#include<iostream>
#include<queue>
//BFS算法 奇怪的电梯

using namespace std;

bool visited[205];//记录是否已经到过这层,最短路径问题,到走过的楼层无意义

struct node//楼层节点
{
	int now;//当前层数
	int count;//当前启用电梯次数
};

queue<node>Q;//用来保存当前楼层节点,先进先出

int kk[205];//第i层上的number

int main()
{
	int n, a, b;
	cin >> n >> a >> b;
	for (int i = 1; i <=n; i++)
		cin >> kk[i];
	Q.push(node{ a, 0 });//入队
	while (not Q.empty())
	{
		node u = Q.front();//提取队首元素
		Q.pop();//弹出队首元素

		if (u.now == b)//是目标楼层,结束
		{
			cout << u.count;
			return 0;
		}

		int df = u.now + kk[u.now];//上楼
		if (df <= n && not visited[df])//是否能走
		{
			visited[df] = true;
			Q.push(node{ df,u.count + 1 });
		}

		df = u.now - kk[u.now];//下楼
		if (df >= 1 && not visited[df])//是否能走
		{
			visited[df] = true;
			Q.push(node{ df,u.count + 1 });
		}
		
	}
	cout << "-1";
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值