暴力递归
一:基础知识:暴力递归就是尝试出所有的方案。
1.1:递归的过程和伪代码模版
- 有明确的不需要继续进行递归的条件(basecase)
- 把问题转化为规模缩小了的同类问题的子问题
- 确定当得到了子问题的结果之后的决策过程
int/void process(一个或者两个变化参数和一些不变的参数) {
if(end_condition) {//递归结束的条件和basecase是一致的,有2种理解方式
end;//结束情境
return; //return value;
}
slove();//递归前的处理方式,递过程进去
process(变化参数变化,不变参数不变);//大规模问题转小规模问题
solve();//递归后的处理,归过程
return;//return value;
}
二:递归问题的思路步骤
2.1:递归能解决的问题(判断问题是否能够递归解决)
- 1.打印机器人运动路径,输出全排列,dfs遍历。。(跟路径有关的仅能递归解决)
- 2.求方法数一个值,求最大最小值,是否存在(既可以递归,又可以dp,还可以记忆搜索)
- 3 递归(自顶向下)(if(存在重复计算))----->记忆化搜索(自顶向下)(每次计算存memo数组)—>dp(自下向顶)
2.2:确定递归模型,并画出思维树或者图(即找到一种方法能够用尝试所有过程)
递归常用的四种模型:**
- 从左到右的尝试模型(int index):arr[i]选择不选择,空位有哪几种选择,该位置是否与后续交换
- 范围上的尝试模型(int left ,int right)
- 多样本位置全对应的尝试模型(string a,string b)
- 寻找业务限制的尝试模型
2.3:明确递归函数的作用(也就是问题所求),并且确定好递归参数(可以编写code边添加确定),带入参数再次确定递归函数作用
2.4:basecase 2种理解,一种是递归的变化参数的终止条件,二是基本案例情况下的返回值,二者统一
2.5:递过程的操作
2.6:递归的调用:参数规模变小,同时还设计到思维树是否同层需要剪枝,多种选择的情况下回溯等(由问题的限制条件决定的)
2.7:归过程的操作
2.8:return ;或者return value;
三:递归常考问题
1.汉罗塔问题
#include<iostream>
using namespace std;
#include<vector>
#include<string>
class Solution {
public:
void hans(int n, string A, string B, string C, int& steps ) {
if (n == 0) return;
if (n == 1) {
cout << " move " << n << " from " << A << " to " << C << endl;;
steps++;
return;
}
hans(n - 1, A, C, B, steps);//将A上面n-1个通过C移到B
cout << " move " << n << " from " << A << " to " << C << endl;//将A最后一个移到C
steps++;
hans(n - 1, B, A, C, steps);//将B上面n-1个通过空的A移到C
}
};
int main()
{
int steps = 0;
Solution slt;
slt.hans(3, "A", "B", "C",steps);
cout << steps << endl;
system("pause");
return 0;
}
//给定一个长度为 n 的可包含重复数字的序列,从中随机选取 m 个数字,输出所有可能的选择方案。
//
//输入格式
//第一行包含两个整数 n, m。
//
//第二行包含 n 个正整数。
//
//输出格式
//按照从小到大的顺序输出所有方案,每行 1 个。
//
//首先,同一行内的数升序排列,相邻两个数用一个空格隔开。
//
//其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面(例如1 3 5 7排在1 3 6 8前面)。
//
//数据范围
//n>0,
//0≤m≤n,
//n + (n−m)≤25,
//序列内所有元素均不大于 n。
//
//输入样例:
//5 3
//1 2 2 3 3
//输出样例:
//1 2 2
//1 2 3
//1 3 3
//2 2 3
//2 3 3
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void process(vector<int>arr, int m, int index, int arrindex, vector<int>path) {
if (index == m) {
for (int i : path) cout << i << " ";
cout << endl;
return;
}
if (arrindex >= arr.size()) return;
vector<bool>used(arr.size(), false);
for (int i = arrindex; i<arr.size(); i++) {
if (used[arr[i]] == false) {
used[arr[i]] = true;
path.push_back(arr[i]);
process(arr, m, index + 1, i + 1, path);
path.pop_back();
}
}
}
int main() {
int n, m;
cin >> n >> m;
vector<int>arr(n);
for (int i = 0; i<n; i++) cin >> arr[i];
sort(arr.begin(), arr.end());
vector<int>path;
process(arr, m, 0, 0, path);
return 0;
}