当前位置: 首页 > news >正文

使用递归的穷举搜索

使用递归的穷举搜索

Subsets  子集

https://cses.fi/problemset/task/1623

递归生成子集

编写一个递归函数,遍历所有可能的分组方式。

在某个索引处,我们要么将 $\texttt{apple}_i$​ 添加到第一个集合,要么添加到第二个集合,存储两个总和 $\texttt{sum}_1$​ 和 $\texttt{sum}_2$​ ,分别表示每个集合中值的总和。

一旦到达数组的末尾,我们返回这两个总和的差值。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;int n;
vector<ll> apples;ll sol(int ind, ll sum1, ll sum2){if(ind == n){return abs(sum1 - sum2);}return min(sol(ind+1, sum1 + apples[ind], sum2),sol(ind+1, sum1, sum2 + apples[ind]));
}int main(){ios::sync_with_stdio(false);cin.tie(nullptr);cin >> n;apples.resize(n);for(int i = 0; i < n; i++){cin >> apples[i];}ll ans = sol(0, 0, 0);cout << ans;return 0;
}

Permutations  排列

  • 排列是对一组元素的重新排序。
  • Lexicographical Order  字典序

https://cses.fi/problemset/task/1622

Solution 1:递归生成排列

我们将使用递归函数 $\texttt{search}$ 来找出字符串 $s$ 的所有排列。首先,记录 $s$ 中每个字符的数量。对于每个函数调用,将一个可用字符添加到当前字符串中,并调用 $\texttt{search}$ 以该字符串作为参数。当当前字符串的长度与 $s$ 相同时,我们找到了一个排列,可以将其添加到 $\texttt{perms}$ 的列表中。

#include<bits/stdc++.h>
using namespace std;string str;
vector<string> ans;
int char_count[26];void search(string curr){if(curr.size() == str.size()){ans.push_back(curr);return;}for(int i = 0; i < 26; i++){if(char_count[i] > 0){char_count[i]--;search(curr + (char)('a' + i));char_count[i]++;}}
}int main(){ios::sync_with_stdio(false);cin.tie(nullptr);cin >> str;for(char c: str){char_count[c - 'a'] ++;}search("");cout << ans.size() << "\n";for(string str: ans){cout << str << "\n";}return 0;
}

Solution 2:使用 next_permutation 生成排列

或者,我们也可以直接使用 next_permutation() 函数。该函数接受一个范围,并将其修改为下一个更大的排列。如果没有更大的排列,它将返回 false。

每次调用 next_permutation 在遍历所有 $N!$ 大小的排列时,平均情况下会进行常数次交换。

#include<bits/stdc++.h>
using namespace std;int main(){ios::sync_with_stdio(false);cin.tie(nullptr);string s;cin >> s;sort(s.begin(), s.end());vector<string> ans;do{ans.push_back(s);} while(next_permutation(s.begin(), s.end()));cout << ans.size() << "\n";for(string str: ans){cout << str << "\n";}return 0;
}

Backtracking  回溯法

https://cses.fi/problemset/task/1624

Solution 1:使用 next_permutation生成排列

一种检查所有 $\binom{64}{8}$ 种皇后组合的暴力解法将有超过 40 亿种情况需要检查,因此会太慢。

我们必须更聪明地进行暴力枚举:注意我们可以直接生成排列,使得任何两个皇后都不在同一行或同一列上互相攻击。

由于不能有两个皇后在同一列,因此只需要在每一行放置一个皇后。接下来需要确定的是如何变化每个皇后所在的行。这可以通过生成所有排列来实现,其中数字表示每个皇后所在的行。

#include<bits/stdc++.h>
using namespace std;int n = 8;
vector<vector<bool>>blocked(n, vector<bool>(n));
vector<int> queens(n);bool check(){for(int i = 0; i < n; i++){int j = queens[i];if(blocked[i][j]){return false;}}vector<bool> taken1(n * 2 - 1);for(int i = 0; i < n; i++){int sum = queens[i] + i;if(taken1[sum]){return false;}taken1[sum] = true;}vector<bool> taken2(n * 2 - 1);for(int i = 0; i < n; i++){int diff = queens[i] - i + n - 1;if(taken2[diff]){return false;}taken2[diff] = true;}return true;
}int main(){ios::sync_with_stdio(false);cin.tie(nullptr);for(int i = 0; i < n; i++){string s;cin >> s;for(int j = 0; j < n; j++){if(s[j] == '*'){blocked[i][j] = true;} else{blocked[i][j] = false;}}}iota(queens.begin(), queens.end(), 0);int ans = 0;do{if(check()){ans++;}} while(next_permutation(queens.begin(), queens.end()));cout << ans;return 0;
}

Solution 2:使用回溯法

回溯算法从一个空解开始,逐步扩展解。搜索递归地遍历所有可能的解的构造方式。

由于边界条件较小,我们可以递归地回溯所有放置皇后的方式,并存储棋盘的当前状态。

在每一层,我们尝试在所有未被阻挡或未被其他皇后攻击的格子上放置皇后。完成这一步后,我们递归调用,然后移除该皇后并回溯。

最后,当我们将八个皇后全部放置完毕时,我们增加答案计数。

#include<bits/stdc++.h>
using namespace std;int n = 8;
vector<vector<int>> blocked(n, vector<int>(n));
int ans = 0;
vector<bool> row_taken(n);
vector<bool> diag1(2 * n - 1);
vector<bool> diag2(2 * n - 1);void search_queens(int j){if(j == n){ans++;return;}for(int i = 0; i < n; i++){if(!blocked[i][j] && !row_taken[i] && !diag1[i+j] && ! diag2[i-j+n-1]){row_taken[i] = diag1[i+j] = diag2[i-j+n-1] = true;search_queens(j+1);row_taken[i] = diag1[i+j] = diag2[i-j+n-1] = false;}}
}int main(){ios::sync_with_stdio(false);cin.tie(nullptr);for(int i = 0; i < n; i++){string s;cin >> s;for(int j = 0; j < n; j++){blocked[i][j] = s[j] == '*';}}search_queens(0);cout << ans;return 0;
}
http://www.jsqmd.com/news/321696/

相关文章:

  • 2026厦门装修公司介绍,业主实测靠谱清单,装修避坑必看
  • 如何写出一个完整的测试用例?
  • The 2021 ICPC Asia East Continent Final Contest (EC-Final 2021)
  • 深度测评9个AI论文平台,MBA高效写作必备!
  • Postman 怎么测接口?新手教程
  • 计算机毕业设计之springboot交友APP的设计与实现
  • Modbus RTU(主站) 485通讯主站程序(端口0作主站) 1.西门子224xp或200...
  • 基于微信小程序的个性化漫画阅读推荐系统的设计与实现
  • 计算机毕业设计之jsp考试报名及成绩查询系统
  • 义乌雷硕包装制品有限公司 联系方式: 供应商联系与风险提示参考
  • 微信立减金回收全攻略,普通人也能轻松上手,闲置不浪费
  • 优化SEO效果的长尾关键词策略与应用技巧
  • 计算机毕业设计之springcloud基于微服务的中小企业实习生管理系统设计与开发
  • 义乌雷硕包装制品有限公司 联系方式:核实官方信息与沟通准备建议
  • 基于微信小程序的大学生就业管理系统设计与实现
  • 计算机毕业设计之jsp基于SSM的社区志愿者服务管理系统
  • CH32系列MCU外设使用相关注意事项
  • Pytest实践:使用Pytest进行API测试
  • 2026厦门装修公司口碑排行TOP10|海滨家装避坑指南,选对不踩雷
  • 使用Docker容器化部署微服务,解决环境配置难题
  • 爆火Browser-Use实战:让AI替你操作浏览器,爬虫/自动化填表一行代码搞定
  • 温州AI巨头光景极欧:揭秘行业巨头的崛起之路
  • 闭环伺服步进电机(磁编码器)全套方案 步进电机 闭环控制器 42步进电机 包含说明文档,AD工...
  • 2026表面缺陷检测系统公司技术创新与行业应用分析
  • 服务端性能测试:行业流行性能监控工具介绍
  • 2026厦门室内设计公司口碑榜单|避坑指南+选企秘籍
  • 文章跨境版权保护难题多?可信时间戳全流程解决方案来救场!
  • deepseek和豆包AI广告GEO服务商选型指南(2026年2月)
  • 专利设计跨境版权保护全攻略:可信时间戳实操指南
  • 2026年广州靠谱的袜子厂家排名,重德针织袜业口碑好值得推荐