深度优先搜索的优化与技巧

迭代加深

DFS在一些问题模型中可能无限扩展,如8数码问题,无限扩展会有些问题,增
加深度限制:假设目标状态所处深度不超过某阈值。人为设定,当搜索深度到达阈
值时直接剪枝,不再往下搜索。
Iterative Deepening Depth - First Search
适用:求最优/深度最低/步数最少解,当问题深度和广度都大的时候
方式:不断放宽迭代深度限制第一次找到的目标状态即为最优解。
迭代加深是深搜和广搜的结合,普通深搜求最优解必须遍历所有状态打擂台得到,
迭代加深后,第一次遇见目标状态即可得到最优解。
深度优先搜索优化-迭代加深(IDDFS)

for(int dep=1;;dep++)
{//限定每次搜索的深度
	if(dfs(1,dep)) break;//找到答案就退出
}

例题1443:【例题4】Addition Chains
n范围较小,初略推出最多十项左右就能得到答案,即答案在搜索树的浅层,可
以使用迭代加深的方法,限制每一次的搜索深度。
例题代码

#include<iostream>
#include<cstring>
using namespace std;
int n,a[105],vis[10005];
bool flag = false;

int dfs(int x,int depth)
{
    if(x>depth)
        return 0;
    if(flag==true)
        return 1;
    bool vis[5500] = {0};
    for (int i = x - 1; i >= 1;i--)
    {
        for (int j = i; j >= 1;j--)
        {
            int s = a[i] + a[j];
            if(vis[s]==1)
                continue;
            if(s>n||s<a[x-1])
                continue;
            a[x] = s;
            vis[s] = 1;
            if(s==n)
            {
                for (int i = 1; i <= x;i++)
                    cout << a[i] << " ";
                cout << endl;
                flag = 1;
                return 1;
            }
            dfs(x + 1, depth);
        }
    }
    return 0;
}

int main()
{
    while(cin>>n&&n)
    {
        memset(a, 0, sizeof(a));
        a[1] = 1;
        flag = false;
        if(n==1)
        {
            cout << 1 << endl;
            continue;
        }
        for (int dep = 2;;dep++)
        {
            if(dfs(2,dep))
                break;
        }     
    }
}

折半搜索

例题P4799 [CEOI2015 Day2]世界冰球锦标赛
例题代码

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll pri[55], p1[5000005], ans, n, m, tot;

void dfs1(int x,ll cost)
{
    if (x==(n>>1)+1)
    { 
        p1[++tot]=cost;
        return;        
    }
    if(cost+pri[x]<=m)
        dfs1(x+1, cost+pri[x]);
    dfs1(x+1, cost);
}

void dfs2(int x,ll cost)
{
    if(x>n)
    { 
        int l=1, r=tot, add=0;
        while (l<=r)
        { 
            int mid=((r-l)>>1)+l;
            if (p1[mid]+cost<=m)
            {
                l=mid+1;
                add=mid;
            }
            else
                r=mid-1;
        }
        ans+=add;
        return;
    }
    if(cost+pri[x]<=m)
        dfs2(x+1, cost+pri[x]);
    dfs2(x+1, cost);
}

int main()
{

    cin>>n>>m;
    for (int i=1;i<=n;i++)
        cin>>pri[i];
    dfs1(1,0);
    sort(p1+1, p1+1+tot);
    dfs2(n/2+1,0);
    cout<<ans;
}

IDA*

A*与迭代加深的结合使用,通过估价函数计算出递归的层数,若大于当前设定的最大层数,直接剪枝

posted @ 2020-08-08 20:19  DSHUAIB  阅读(440)  评论(0)    收藏  举报