• 搜索—迭代加深


    概念定义

    深度优先搜索是选择一个分支,直到尽头才会开始回溯。但在遇到搜索树的每个节点的分支数目非常多,并且答案其实只是在很浅的节点上。那么如果在一开始深搜选错了分支,就很可能在不包含答案的深层子树上浪费大量的时间。

    那么此时,我们就可以使用迭代加深的思想,从小到大限制搜索的深度。如果在当前深度限制下搜索不到答案,那么就增加深度,重新进行一次搜索。

    虽然理论上重新搜索的代价似乎是挺不必要的,但是随着层数的深入,每层节点数会呈指数性增长。这点重复量和深层子树的规模相比,不值一提。

    总之,当搜索树规模随着层次的深入增长很快,并且我们能够确保答案在一个较浅层的节点时,就可以用这个技巧。

    题目中的ShowTime

    Addition chains (POJ 2248)

    题来

    这道题,是搜索枚举题。在最坏的情况下深度可以达到100。但由于题目仅仅要求一个短序列的可行解,那么就算从1开始枚举,深度也绝不会超过30层(口胡)。这就符合迭代加深的思想,即答案一定在浅层里。

    那么这道题需要一个数组path来存储当前确定好的序列是什么

    并加入如下剪枝优化:

    1.path[0—u-1],从大到小枚举。这样可以更快的接近n,以达到序列最短的目的。

    2.判重。对于某两组不同的数,其相加之和可能相同。申请一个bool数组来判重。如果该数已经被搜索过,则直接跳过搜索。

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=110;
    int path[N];
    int n; 
    bool dfs(int u,int depth){
        if(u==depth){
            return path[u-1]==n;
        }
        bool pc[N]={false};
        for(int i=u-1;i>=0;i--){
            for(int j=i;j>=0;j--){
                 int s=path[i]+path[j];
                 if(s>=path[u-1]&&s<=n&&!pc[s]){
                     pc[s]=true;
                     path[u]=s;
                     if(dfs(u+1,depth)) return true;
                 }
                 
            }
        }
    }
    int main(){
        while(cin>>n,n){
            int depth=1;
            path[0]=1;
            while(!dfs(1,depth))depth++;
            for(int i=0;i<depth;i++){
                cout<<path[i]<<" ";
            }
            cout<<endl;
        }
    } 
  • 相关阅读:
    Coalesce (MS SQL Server)——取指定内容(列)中第一个不为空的值
    SQL 函数NULLIF、NULL、ISNULL、COALESCE、IIF
    oracle 分组后取每组第一条数据
    oracle判断是否包含字符串的方法
    Oracle 查询字段不包含多个字符串方法
    [oracle] to_date() 与 to_char() 日期和字符串转换
    Oracle中保留两位小数
    Oracle 树操作、递归查询(select…start with…connect by…prior)
    联合查询更新表数据
    WCF 之 生成元数据和代理
  • 原文地址:https://www.cnblogs.com/Uninstalllingyi/p/11284994.html
Copyright © 2020-2023  润新知