当前位置:   article > 正文

深搜+记忆化+回溯_回溯加记忆化搜索

回溯加记忆化搜索

        今天我又来讲搜索了,开始我觉得搜索难,可懂了以后其实简单得要命。来看例题:

        一.烤鸡(来自这以后题目都是在这找的)

        题目描述:

        Hanke他有 1010 种配料(芥末、孜然等),每种配料可以放 11 到 33 克,任意烤鸡的美味程度为所有配料质量之和。现在, Hanke 想要知道,如果给你一个美味程度 n ,请输出这 1010 种配料的所有搭配方案。

        输出格式:

        第一行,方案总数。

        第二行至结束,1010 个数,表示每种配料所放的质量,按字典序排列。

        如果没有符合要求的方法,就只要在第一行输出一个 00。

______________________________________________________________

        这就是一个极其典型的弱化版搜索,或许有人会用10重循环,但那不是正解!!

        先看代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n,f[11],ans;
  4. int df(int r,int z){这个是记录数量
  5. if(r==9&&n-z<=3){//不要再递归了,能简单尽可能的简单点
  6. ans++;
  7. return 0;
  8. }
  9. if(n-z>3*(10-r)){//判断退出,否则会MLE
  10. return 0;
  11. }
  12. for(int i=1;i<=n-z-1&&i<=3;i++){//递归
  13. df(r+1,z+i);
  14. }
  15. return 0;
  16. }
  17. int dfs(int r,int z){
  18. if(r==9&&n-z<=3){
  19. for(int i=1;i<10;i++){
  20. printf("%d ",f[i]);//输出记录数字
  21. }
  22. printf("%d\n",n-z);
  23. return 0;
  24. }
  25. if(n-z>3*(10-r)){
  26. return 0;
  27. }
  28. for(int i=1;i<=n-z-1&&i<=3;i++){
  29. f[r+1]=i;//记录
  30. dfs(r+1,z+i);
  31. }
  32. return 0;
  33. }
  34. int main(){
  35. cin>>n;
  36. if(n>30){//特判
  37. cout<<0<<endl;
  38. return 0;
  39. }
  40. if(n<10){//判断
  41. cout<<0<<endl;
  42. return 0;
  43. }
  44. for(int i=1;i<=n-9&&i<=3;i++){//计算方案数
  45. df(1,i);
  46. }
  47. cout<<ans<<endl;
  48. for(int i=1;i<=n-9&&i<=3;i++){//输出具体方案
  49. f[1]=i;//记录
  50. dfs(1,i);
  51. }
  52. return 0;
  53. }

        这还没有用到回溯法,但可以先打个基础;

        来看第二题:

        二.选数(回溯)

        题目自己看,不再多说:

        

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n,m,s[22],ans,f[22];
  4. int ss(int x){//这个是判断素数
  5. if(x%2==0&&x>2)//不要把2漏了
  6. return 0;
  7. for(int i=3;i<x;i+=2){//最简单的判断素数法
  8. if(x%i==0)
  9. return 0;
  10. }
  11. return 1;
  12. }
  13. int dfs(int k,int z,int x){
  14. if(k==m){
  15. if(ss(z))//如果是素数答案+1
  16. ans++;
  17. return 0;
  18. }
  19. for(int i=x+1;i<=n;i++){
  20. f[i]=1;//回溯
  21. dfs(k+1,z+s[i],i);//搜索
  22. f[i]=0;
  23. }
  24. return 0;
  25. }
  26. int main(){
  27. cin>>n>>m;
  28. for(int i=1;i<=n;i++)
  29. cin>>s[i];
  30. for(int i=1;i<=n-m+1;i++){//同上
  31. f[i]=1;
  32. dfs(1,s[i],i);
  33. f[i]=0;
  34. }
  35. cout<<ans<<endl;//输出
  36. return 0;
  37. }

        是不是很简单?再来个搜索+记忆化+回溯:

        三.枚举排列

        代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n,k,f[11],v[11];
  4. int dfs(int x,int r){
  5. f[r]=x;//简单记忆化
  6. if(r==k){
  7. for(int i=1;i<k;i++){//简单输出
  8. printf("%d ",f[i]);
  9. }
  10. printf("%d\n",f[k]);
  11. return 0;
  12. }
  13. for(int i=1;i<=n;i++){
  14. if(!v[i]){//简单回溯
  15. v[i]=1;
  16. dfs(i,r+1);
  17. v[i]=0;
  18. }
  19. }
  20. return 0;
  21. }
  22. int main(){
  23. cin>>n>>k;
  24. for(int i=1;i<=n;i++){
  25. v[i]=1;
  26. dfs(i,1);
  27. v[i]=0;
  28. }
  29. return 0;
  30. }

        说实话以上的题目数据太弱了,不过适合新手练习,在看代码前可以自己尝试一下,记得留下赞来给个支持!!!

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号