【深搜】
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;
}