zoukankan      html  css  js  c++  java
  • 回溯算法理解

    一、算法含义

    回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思路是:暴力算法的改进,在通过遍历所有路径基础上,通过回溯(往回找)筛除不可能的路径,提高效率。

    二、解题步骤:

    1.确定一个解空间,它包含问题的解;
    2.利用适于搜索的方法组织解空间;
    3.利用深度优先法搜索解空间;
    4.利用剪枝(约束函数、限界函数)避免移动到不可能产生解的子空间。

    三、算法框架 

    bool constraint(int t){};//约束函数
    bool bound(int t){};//限界函数
    
    void backtrack(int t){   
      if(t > n) output(x);   
      else{   
        for(int i = f(n,t); i <= g(n,t);i++){ //该节点的子节点(分量的所有下一个分量)
        x[t] = h(i);
        if(constraint(t) && bound(t))
          backtrack(t+1); }
        }
    }

    四、例题

    7-1 子集和问题 (50 分)

    设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,使S1中的元素之和为c。试设计一个解子集和问题的回溯法。

    输入格式:

    输入数据第1行有2个正整数n和c,n表示S的大小,c是子集和的目标值。接下来的1行中,有n个正整数,表示集合S中的元素。 是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。

    输出格式:

    输出子集和问题的解,以空格分隔,最后一个输出的后面有空格。当问题无解时,输出“No Solution!”。

    输入样例:

    5 10
    2 2 6 5 4

    输出样例:

    2 2 6 

    代码:

    #include <iostream>
    using namespace std;
    int flag =0;
    int s[100000];
    int selec[100000];
    int fin_selec[100000];
    
    void backTrack(int target,int t,int sum ,int n){
        if(flag==1)return;
        if (t>=n) {
            if (sum == target) {
                for (int i=0; i<n; i++) {
                    fin_selec[i] = selec[i];
                }
                flag = 1;
                return;
            }
            return;
        }
        
        if (sum+s[t]<=target) {
            selec[t]=1;
            sum +=s[t];
            backTrack(target, t+1, sum, n);
            selec[t]=0;
            sum -= s[t];
        }
        selec[t] =0;
        backTrack(target, t+1, sum, n);
    }
    
    int main(){
        int n,target;
        cin>>n>>target;
        for (int i=0; i<n; i++) {
            cin>>s[i];
            selec[i]=0;
            fin_selec[i]=0;
        }
        int sum=0;
        for (int i=0; i<n; i++) {
            sum+=s[i];
            }
        if (sum<target) {
            cout<<"No Solution!"<<endl;
            exit(0);
        }
        backTrack(target, 0, 0, n);
        if (flag==1) {
            for (int i=0; i<n; i++) {
    //            cout<<fin_selec[i];
                if (fin_selec[i]==1) {
                    cout<<s[i]<<" ";
                }
            }
        }else cout<<"No Solution!"<<endl;
        return 0;
    }

    五、总结

    由于对算法的不够熟悉,导致细节出问题,思维不够发散,模版很好用,再加上对约束函数限界函数的完善就是整道题的清晰思路。

  • 相关阅读:
    千亿美元规模,云计算的下半场将走向何方?
    巧用云原生能力和工具,提升云上运维效率
    基础设施代码化(IaC)的自动化配置与编排
    盘点2020 | 阿里云弹性计算年度关键词:快、弹、稳
    整体算力提升40% 芯片级安全防护 | 阿里云发布第七代ECS云服务器
    真正云原生的智能运维体系,阿里云发布ECS自动化运维套件
    安装wireshark
    查看linux的登录日志 centos7
    CentOS查看系统当前登录用户信息的4种方法
    free -m查询内存使用情况,祥解
  • 原文地址:https://www.cnblogs.com/Adam-Ye/p/10156867.html
Copyright © 2011-2022 走看看