当前位置:   article > 正文

acwing-蓝桥杯C++ AB组辅导课Day1-递归_awcing蓝桥杯辅导课

awcing蓝桥杯辅导课

感谢梦翔老哥的蓝桥杯C++ AB组辅导课~

省一刷200题        国赛拿成绩300题

比赛考察的是各种模型的熟练度,可以从dfs的角度比较各个模型与当前问题的匹配程度。

常见时间复杂度,根据时间复杂度可以判别是否可以选用这个解题思路

 写递归的时候,可以考虑将递归写成递归搜索树的形式,比较便于理解:

常见的数字:

递归实现指数型枚举:

递归的思路就是找到一个顺序不重不漏的遍历所有情况。本题的思路就是遍历每个位置,考虑每个位置选或不选的情况。

ac代码:

从第0个位置开始枚举,到第n-1的位置。先写边界,边界写完可以考虑上面图中的某个节点(红圈),设置某个位置的数字后递归回溯要还原现场。

递归是怎么实现回溯的呢?看下列代码,dfs(u+1)的位置,执行到此处代码会进入到新的函数当中,当dfs(u+1)执行结束的时候,会跳转到目前执行的下一行,为了不影响“选”的决策,需要把位置设置为原来的0。建议与上面的红圈图搭配着看比较清晰。

其实本题可以不用恢复现场,并且state[u] = 0 会被state[u] = 1 和下次dfs中的status[u]=2覆盖掉,因为最后输出只在递归树的末端,此时所有的位置都是1或者2,没有0。

递归实现排列型枚举:

做递归题建议先把递归搜索树写出来,明确思路。会简单很多。

思路1:枚举每个数字放到哪个位置 ×        由于题目要求输出字典序较小的数字,模拟了一下发现不能满足题目要求。

思路2:枚举每个位置放哪个数字 √

递归搜索树

AC代码:

时间复杂度分析:

根据递归搜索树分析,第一层O(n),第二层nxn,第三层nx(n-1)xn...        视频后面还有个证明,大概是使用了放缩,将红框的内容全部加起来,提出来个n,剩余的部分可以放缩成小于等于3倍的n!。所以最终的时间复杂度为nxn!。

习题1:

递归实现组合型枚举

思路:

一开始看到这个题,感觉跟例题里的枚举每个位置放哪个数基本一致,以为稍微改一下数组大小就行。但题意要求输出升序序列。所以在这基础上需要进行剪枝,123是可以的,132就是不行的。所以在填写位置的时候,将目前已经填写的数字(3)与即将要填入的数字(2)进行比较,如果已经填写的数字大于即将填入的数字,那就不能填,再往后看看有没有合适的数。

AC代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. vector<int> ans;
  4. bool state[26];
  5. int m,n; //m表示位置个数,n表示数字个数
  6. void dfs(int u){//枚举位置
  7. if(u == m){
  8. for(int i=0;i<m;i++){
  9. cout<<ans[i]<<" ";
  10. }
  11. cout<<endl;
  12. return;
  13. }
  14. int num = -1;
  15. for(int i=1;i<=n;i++){
  16. if(ans.size()!=0){
  17. num = ans[ans.size()-1];
  18. }
  19. if(!state[i]&&(i>num)){
  20. ans.push_back(i);
  21. state[i] = true;
  22. dfs(u+1);
  23. ans.pop_back();
  24. state[i] = false;
  25. }
  26. }
  27. }
  28. int main(){
  29. cin>>n>>m;
  30. dfs(0);
  31. return 0;
  32. }

习题2:带分数

自己没想出来,引用一下人家的题解(没想到竟然如此暴力):

代码如下(代码自己想着敲得):

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. vector<int> ans;
  4. bool status[10];
  5. int cnt = 0;
  6. int calc(int i,int j){
  7. int num = ans[i];
  8. while(i<j){
  9. i++;
  10. num = num*10 + ans[i];
  11. }
  12. return num;
  13. }
  14. void dfs(int u,int target){
  15. if(u == 9){
  16. //对ans进行处理,走到这里正好凑够9位
  17. for(int i=0;i<7;i++){ //这里注意循环到7
  18. for(int j = i+1;j<8;j++){ //这里注意循环到8 不然没有c这个数了
  19. int a = calc(0,i);
  20. // printf("%d",a); wc加了个printf就超时了
  21. int b = calc(i+1,j);
  22. int c = calc(j+1,8);
  23. if((a*c+b) == (target * c)) cnt++;
  24. }
  25. }
  26. return;
  27. }
  28. for(int i=1;i<=9;i++){
  29. if(!status[i]){
  30. ans.push_back(i);
  31. status[i] = true;
  32. dfs(u+1,target);
  33. status[i] = false;
  34. ans.pop_back();
  35. }
  36. }
  37. }
  38. int main(){
  39. int n;
  40. scanf("%d",&n);
  41. dfs(0,n);
  42. printf("%d",cnt);
  43. return 0;
  44. }


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/916216
推荐阅读
相关标签
  

闽ICP备14008679号