【Sowu_0077】搜索作业

【深搜】

1、全排列

模板题:洛谷 P1706 全排列问题
题解:就是。。。先这样,在那样,再这样就行了。(一直往下深搜的思想,和回溯的思想。)
AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define N 10
int n;
int visit[N] = {0};//数没用过标0,数用过标1
int path[N];
//每一次递归搜索的是第 depth 个箱子中可以放什么数字 我是这么理解的。
void dfs(int depth) {
//假设有n个字符要排列,把他们依次放到n个箱子中

//先要检查数字是否被用过,手中还有什么数字,把他们放进并标记。

//放完一次要恢复初始状态,当到n+1个箱子时,一次排列已经结束

	if (depth == n+1)//判断边界
	{
		for (int i = 0; i < n; i++)
			printf("%5d", path[i]);
		cout << endl;
		return;
	}
	for (int i = 1; i <=n; i++) {//遍历查找 第depth个箱子中 ,能放什么数字
		if (visit[i] == 0)//若数字没有被用过
		{
		    path[depth-1] = i;//则可以往箱子里放这个数
			visit[i]= 1;//放完数后数字要标记为已用过
			dfs(depth + 1);//继续搜索下一个箱子
			visit[i] = 0;//回溯 数字用过后要回到没用过状态
		}
	}
}
int main() {

	cin >> n;
	dfs(1);//从第一个箱子开始
	return 0;
}

2、八皇后

题目:洛谷 P1219 [USACO1.5]八皇后
题解:只是判断困难了一点。以后要记住:主对角线上各数组下标之差相等;斜对角线上各数组下标之和相等。
AC代码:

#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define N 17
bool col[N], tx[N], ty[N];
int path[N] = { 0 };
int n,ans=0;
void dfs(int depth) {
	if (depth >n) {
		ans++;
		if (ans <= 3)
		{
			for (int i = 1; i < n ; i++)
				cout << path[i] << " ";
			cout << path[n] << endl;
		}
		return;
	}
	for (int i = 1; i <= n; i++) {//试图把数字放在(depth,i)
		if (col[i] || tx[depth - i + n] || ty[depth + i])
			continue;
		else
		{
			path[depth] = i;
			col[i] = 1, tx[depth - i + n] = 1, ty[depth + i] = 1;
			dfs(depth + 1);
			col[i] = 0, tx[depth - i + n] = 0, ty[depth + i] = 0;
		}
	}
}
int main() {
	cin >> n;
	dfs(1);
	cout << ans;
	return 0;
}

3、选数

题目:洛谷 P1036 选数
题解:要注意的是搜索出来的每一种情况都是升序数组(防止数据重复)

#include<iostream>
#include<algorithm>
using namespace std;
#define N 5000007
int num[N];
bool visit[N];
int n, k,ans=0;
bool isSuShu(int n) {
	if (n <= 1)
		return 0;
	else
	{
		int i;
		for (i = 2; i < n; i++) {
			if (n % i == 0)
				break;
		}
		if (i >= n)
			return 1;
		else
			return 0;
	}
}
void dfs(int depth,int l) {
	if (depth> k)
	{
		int nums = 0;
		for (int i = 1; i <= n; i++) {
			if (visit[i]) {
				nums += num[i];
				/*cout << num[i] << " ";*/
	                      }

		}
		/*cout << endl;*/
		if(isSuShu(nums))
		   ans++;
		return;
	}
	for (int i = l; i <= n; i++) {
		if (visit[i])
			continue;
		visit[i] = 1;
		dfs(depth + 1,i+1);//i+1是为了防止数据重复,我理解的是我们找的组合都是升序数组
		visit[i] = 0;	
	}
}
int main() {
	cin >> n >> k;
	for (int i = 1; i <= n; i++)
		cin >> num[i];
	dfs(1,1);
	cout << ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43502713/article/details/107892969
今日推荐