一、AcWing 842. 排列数字
1.1 问题描述
1.2 问题分析
-
从第0个位置开始dfs;
-
dfs结束条件:当搜索到第n个位置时,说明0~n-1的位置已经排列好了;
-
然后在当前u位置上,从1~n放符合条件的数,找到后继续向下一个位置搜索;
-
从下面回来后,恢复现场;
1.3 问题解决
#include <iostream>
using namespace std;
const int N = 15;
int n;
int a[N];
bool st[N];
void dfs(int u)
{
if(u == n)
{
for(int i = 0; i < n; i++) printf("%d ", a[i]);
printf("\n");
return ;
}
for(int i = 1; i <= n; i++)
{
if(st[i] == false)
{
a[u] = i;
st[i] = true;
dfs(u+1);
st[i] = false;
}
}
}
int main()
{
scanf("%d", &n);
dfs(0);
return 0;
}
二、AcWing 843. n-皇后问题
2.1 问题描述
2.2 问题分析
-
从第0层开始搜索;
-
搜索结束条件:搜索到第n层结束;
-
在当前u层找到符合条件(当前列、斜边和反斜边都为false)的列放入字符Q;
-
dfs到下一层;
-
回溯后恢复现场;
2.3 问题解决
#include <cstring>
#include <iostream>
using namespace std;
const int N = 15;
int n;
char g[N][N];
bool col[N], x[N], fx[N];
void dfs(int u)
{
if(u == n)
{
for(int i = 0; i < n; i++)
puts(g[i]);
puts("");
return ;
}
for(int i = 0; i < n; i++)
{
if(!col[i] && !x[u-i] && !fx[u+i])
{
g[u][i] = 'Q';
col[i] = true, x[u-i] = true, fx[u+i] = true;
dfs(u+1);
col[i] = false, x[u-i] = false, fx[u+i] = false;
g[u][i] = '.';
}
}
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
memset(g[i], '.', n);
dfs(0);
return 0;
}
三、AcWing 844. 走迷宫
3.1 问题描述
3.2 问题分析
bfs模板:
定义队列
队列初始化
while(队列不为空)
{
取队头元素
…
}
3.3 问题解决
#include <cstring>
#include <iostream>
#include <queue>
#define x first
#define y second
using namespace std;
const int N = 110;
typedef pair<int, int> PII;
int n, m;
int g[N][N];
int d[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int bfs()
{
queue<PII> q;
memset(d, -1, sizeof(d));
d[0][0] = 0;
q.push({0, 0});
while(!q.empty())
{
PII t = q.front();
q.pop();
for(int i = 0; i < 4; i++)
{
int x = t.x + dx[i], y = t.y + dy[i];
if(x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)
{
d[x][y] = d[t.x][t.y] + 1;
q.push({x, y});
}
}
}
return d[n-1][m-1];
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
scanf("%d", &g[i][j]);
printf("%d\n", bfs());
return 0;
}
四、AcWing 845. 八数码
4.1 问题描述
4.2 问题分析
暂时还是没有理解
4.3 问题解决
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <queue>
using namespace std;
int bfs(string state)
{
queue<string> q;
unordered_map<string, int> d;
q.push(state);
d[state] = 0;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
string end = "12345678x";
while (q.size())
{
auto t = q.front();
q.pop();
if (t == end) return d[t];
int distance = d[t];
int k = t.find('x');
int x = k / 3, y = k % 3;
for (int i = 0; i < 4; i ++ )
{
int a = x + dx[i], b = y + dy[i];
if (a >= 0 && a < 3 && b >= 0 && b < 3)
{
swap(t[a * 3 + b], t[k]);
if (!d.count(t))
{
d[t] = distance + 1;
q.push(t);
}
swap(t[a * 3 + b], t[k]);
}
}
}
return -1;
}
int main()
{
char s[2];
string state;
for (int i = 0; i < 9; i ++ )
{
cin >> s;
state += *s;
}
cout << bfs(state) << endl;
return 0;
}
五、一本通 1317 组合的输出
5.1 问题描述
5.2 问题分析
类似排列数字
5.3 问题解决
#include <iostream>
using namespace std;
const int N = 25;
int a[N];
bool st[N];
int n, r;
void dfs(int u)
{
if(u == r)
{
int i;
for(i = 0; i < r-1; i++) printf("%3d", a[i]);
printf("%3d\n", a[i]);
}
for(int i = 1; i <= n; i++)
{
if(!st[i] && i > a[u-1])
{
a[u] = i;
st[i] = true;
dfs(u+1);
st[i] = false;
}
}
}
int main()
{
cin >> n >> r;
dfs(0);
return 0;
}
六、一本通 1318 自然数的拆分
6.1 问题描述
6.2 问题分析
dfs解决
6.3 问题解决
#include <cstring>
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int n;
int a[N];
int s;
void dfs(int u)
{
if(s == n)
{
cout << n << '=';
int i;
for(i = 0; i < u-1; i++) cout << a[i] << '+';
cout << a[i] << endl;
return ;
}
for(int d = 1; d < n; d++)
{
if(s+d <= n && d >= a[u-1])
{
a[u] = d;
s += d;
dfs(u+1);
s -= d;
}
}
}
int main()
{
cin >> n;
dfs(0);
return 0;
}