递推与递归和DFS深度优先搜索
递推与递归和DFS深度优先搜索
习题课
递推/ 递归 / DFS
P2089 烤鸡 指数
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long
#define yes cout<<"YES"<<'\n'
#define no cout<<"NO"<<'\n'
using namespace std;
const int N = 100008;
int n;
int ans;
vector <vector<int> > res;//储存结果
vector <int> a;//储存每次搜到的答案
void dfs(int x) {
if (x >= 10) {//搜到第10层的时候开始判断
int sum = 0;
for (int i = 0; i < (int)a.size(); i++) {
sum = sum + a[i];//将这10个数加起来
}
if (sum == n) {//如果满足条件
ans++;//结果加1
res.push_back(a);//放入结果数列
}
return;//返回
}
for (int i = 1; i <= 3; i++) {//开始枚举选几克调料
a.push_back(i);//放入数列
dfs(x + 1);//递归过去选下一个数
a.pop_back();//恢复现场
}
}
signed main () {
cin >> n;
dfs(0);//开始dfs
cout << ans << '\n';//打印所有的次数
for (int i = 0; i < (int)res.size(); i++) {//打印结果
for (int j = 0; j < (int)res[i].size(); j++) {
cout << res[i][j] << ' ';
}
cout << '\n';
}
return 0;
}
P1088 火星人 全排列
P1149 火柴棒等式 指数 + 预处理
P2036 PERKET 指数
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long
#define yes cout<<"YES"<<'\n'
#define no cout<<"NO"<<'\n'
using namespace std;
const int N = 15;
int n;
int arr[N];
int brr[N];
int st[N];//0代表未处理,1代表已经选,2代表不选
int ans = 99999999999999;//结果足够大
void dfs(int x) {
if (x > n) { //选择了n次之后的结果
int s = 1, b = 0;//计算当前酸度和苦度
int flag = 0;//标准变量
for (int i = 1; i <= n; i++) {
if (st[i] == 1) {//如果当前选了这个数
flag = 1;
// cout<<arr[i]<<' '<<brr[i];
s = s * arr[i];
b = b + brr[i];//计算苦度和酸度
}
}
if (flag == 1) {//如果当前会更新酸度和苦度
ans = min(abs(s - b), ans);//更新ans
}
// cout<<'\n';
return;
} else {
st[x] = 2; //不选这个数
dfs(x + 1); //递归到下一层
st[x] = 0; //恢复现场
st[x] = 1; //选这个数
dfs(x + 1); //递归到下一层
st[x] = 0; //恢复现场
}
}
signed main () {
std::ios::sync_with_stdio(false), std::cin.tie(nullptr), std::cout.tie(nullptr);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> arr[i] >> brr[i];
}
dfs(1);
cout << ans << '\n';//打印
return 0;
}
P1135 奇怪的电梯 暴力
迷宫问题
一道很经典的DFS迷宫问题
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long
#define yes cout<<"YES"<<'\n'
#define no cout<<"NO"<<'\n'
using namespace std;
int sx, sy, fx, fy;
const int N = 9;
int n, m;
char mp[N][N];//地图
int dx[6] = {1, -1, 0, 0};
int dy[6] = {0, 0, 1, -1};
bool st[N][N];//状态数组
;
int ans = 0;
void dfs(int x, int y) {
if (x == fx && y == fy) {//到达终点
ans++;//路径加1
return;
}
for (int i = 0; i < 4; i++) {
// cout<<x+dx[i]<<' '<<y+dy[i]<<'\n';
if ((x + dx[i] >= 1 && x + dx[i] <= n && y + dy[i] >= 1 && y + dy[i] <= m) && mp[x + dx[i]][y + dy[i]] == '.') {//判断有没有出地图范围以及当前地图的点能不能走
if (st[x + dx[i]][y + dy[i]] == false) {//当前没有被访问过
st[x + dx[i]][y + dy[i]] = true;//标记为访问
dfs(x + dx[i], y + dy[i]);//继续深搜
st[x + dx[i]][y + dy[i]] = false;//恢复现场
}
}
}
}
signed main () {
memset(mp, '.', sizeof(mp));//'.'代表可以通过
cin >> n >> m;
int t;
cin >> t;
cin >> sx >> sy >> fx >> fy;
while (t--) {
int x, y;
cin >> x >> y;
mp[x][y] = '#';//'#'代表是障碍
}
// for(int i=1;i<=n;i++){
// for(int j=1;j<=m;j++){
// cout<<mp[i][j];
// }
// cout<<'\n';
//
//
// }
st[sx][sy] = true;//起点标记为已经搜索过
dfs(sx, sy);//开始搜索
cout << ans << '\n';//打印结果
return 0;
}
Flood Fill 洪水灌溉
使用洪水灌溉算法
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long
#define yes cout<<"YES"<<'\n'
#define no cout<<"NO"<<'\n'
using namespace std;
const int N = 110;
int n, m;
char mp[N][N];
bool st[N][N];
int dx[] = {1, -1, 0, 0, 1, 1, -1, -1};//向八个方向试探
int dy[] = {0, 0, 1, -1, 1, -1, -1, 1};
int ans = 0;
/*
进行深度优先搜索
*/
void dfs(int x, int y) {
for (int i = 0; i < 8; i++) {
int a = x + dx[i];
int b = y + dy[i];
//如果这个点没有访问过,并且在范围之内.并且可以不是障碍
if (st[a][b] == false && a >= 1 && a <= n && b >= 1 && b <= m && mp[a][b] == 'W') {
st[a][b] = true;//标记为已经访问
dfs(a, b);//先下搜索
}
}
}
signed main () {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> mp[i][j];
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (st[i][j] == false && mp[i][j] == 'W') {//找到一个点开始洪水灌溉
st[i][j] = true;//标记为已经访问
dfs(i, j);//开始深搜
ans++;//答案加1
}
}
}
cout << ans << '\n';
return 0;
}
也是洪水灌溉算法
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long
#define yes cout<<"YES"<<'\n'
#define no cout<<"NO"<<'\n'
using namespace std;
const int N = 110;
int n, m;
char mp[N][N];
bool st[N][N];
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
int ans = 0;
void dfs(int x, int y) {
for (int i = 0; i < 4; i++) {//4个方向
int a = x + dx[i];
int b = y + dy[i];
//没被访问并且,没有越界,并且字符不为0;
if (st[a][b] == false && a >= 1 && a <= n && b >= 1 && b <= m && mp[a][b] != '0') {
st[a][b] = true;//标记为访问
dfs(a, b);//继续深度搜索
}
}
}
signed main () {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> mp[i][j];
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (st[i][j] == false && mp[i][j] != '0') {//洪水灌溉
st[i][j] = true;//标记为访问
dfs(i, j);
ans++;//答案加1
}
}
}
cout << ans << '\n';
return 0;
}
DFS
acw1114.棋盘问题 排列
P1025 数的划分 组合
P1019 单词接龙 指数 + 预处理