zoukankan      html  css  js  c++  java
  • dfs剪枝与优化

    搜索树

    剪枝方法

    1.优化搜索顺序

    2.排除等效冗余

    3.可行性

    4.最优性(估价)

    5.记忆化(树形不会重复计算时不需要)

    A.针对每个维度边界信息缩放、推倒

    B.计算未来最少花费

    C.结合各维度的联系

    P1120 小木棍 

    https://www.luogu.org/problemnew/show/P1120

    bool dfs(int p,int u,int x)
    {
      if(p>cnt) return 1;
      if(u==len) return dfs(p+1,0,1);
      int lf=0;
      FOR(i,x,n)
        if((!vis[i])&&a[i]+u<=len&&a[i]!=lf)//剪枝2
          {
        vis[i]=1;
        if(dfs(p,a[i]+u,i+1)) return 1;
        vis[i]=0;lf=a[i];
        if(u+a[i]==len||u==0) return 0;//剪枝3.4
          }
      return 0;
    }
    int main()
    {
      //freopen("hh.in","r",stdin);
      nnn=rd();
      FOR(i,1,nnn)
      {
        int tptp=rd();
        if(tptp>50) continue;
        a[++n]=tptp,cc+=a[n],gmax(mx,a[n]);
      }
      sort(a+1,a+n+1,greater<int>() );
      //FOR(i,1,n) cout<<a[i]<<" ";cout<<endl;
      for(len=mx;len<=cc;++len)
        {
          if(cc%len) continue;
          cnt=cc/len;
          memset(vis,0,sizeof(vis));
          if(dfs(1,0,1)){cout<<len;break;}
        }
      return 0;
    }

    P1731 [NOI1999]生日蛋糕

    https://www.luogu.org/problemnew/show/P1731

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define FOR(i,a,b) for(register int i(a);i<=b;++i)
    #define For(i,a,b) for(register int i(a);i>=b;--i)
    int mins[20],minv[20];
    int ans=1<<30,s;
    bool prune(int maxh,int maxr,int n,int v)
    {
        int cc=0;
        FOR(i,0,n-1) cc+=(maxh-i)*(maxr-i)*(maxr-i);
        if(cc<v) return 1;
        else return 0;
    }
    void dfs(int maxh,int maxr,int n,int v,int m)
    {
        if(n==0)
        {
            if(v) return;
            ans=min(ans,s);
        }
        if(s+mins[n]>ans) return;
        if(maxh<n||maxr<n) return;
        if(minv[n]>v)  return;
        if(prune(maxh,maxr,n,v)) return;
        For(i,maxr,n)
        {
            if(n==m) s=i*i;
            For(j,maxh,n)
            {
                s+=2*i*j;
                dfs(j-1,i-1,n-1,v-i*i*j,m);
                s-=2*i*j;
            }
        }
    }
    int main()
    {
        int n,m;scanf("%d%d",&n,&m);
        FOR(i,1,m)
            mins[i]=mins[i-1]+2*i*i,
            minv[i]=minv[i-1]+i*i*i;
        if(n<minv[m]) printf("0");
        else
        {
            int maxh=(n-minv[m-1])/(m*m)+1;
            int maxr=sqrt((n-minv[m-1])/m)+1;
            dfs(maxh,maxr,m,n,m);
            if(ans==1<<30) printf("0");
            else printf("%d",ans);
        }
    
        return 0;
    }

    迭代加深

    a.搜索树规模增长快

    b.从小到大限制深度

     双向搜索

    “终态”明确,路径可逆

    CH2401 送礼物

    http://contest-hunter.org:83/contest/0x20%E3%80%8C%E6%90%9C%E7%B4%A2%E3%80%8D%E4%BE%8B%E9%A2%98/2401%20%E9%80%81%E7%A4%BC%E7%89%A9

    先从前(N/2+2)中选若干个,存放,排序,去重

    再枚举后一半,二分查找对应的前一半的值

     1 void dfs1(int i, unsigned int sum) {
     2     if (i == half) {
     3         a[++m] = sum;
     4         return;
     5     }
     6     dfs1(i + 1, sum);
     7     if (sum + g[i] <= w) dfs1(i + 1, sum + g[i]);
     8 }
     9 
    10 void calc(unsigned int val) {
    11     int rest = w - val;
    12     int l = 1, r = m;
    13     while (l < r) {
    14         int mid = (l + r + 1) / 2;
    15         if (a[mid] <= rest) l = mid; else r = mid - 1;
    16     }
    17     ans = max(ans, a[l] + val);
    18 }
    19 
    20 void dfs2(int i, unsigned int sum) {
    21     if (i == n + 1) {
    22         calc(sum);
    23         return;
    24     }
    25     dfs2(i + 1, sum);
    26     if (sum + g[i] <= w) dfs2(i + 1, sum + g[i]);
    27 }
    28 
    29 int main() {
    30     cin >> w >> n;
    31     for (int i = 1; i <= n; i++) scanf("%d", &g[i]);
    32     sort(g + 1, g + n + 1);
    33     reverse(g + 1, g + n + 1);
    34     half = n / 2 + 3;
    35     dfs1(1, 0);
    36     sort(a + 1, a + m + 1);
    37     m = unique(a + 1, a + m + 1) - (a + 1);
    38     dfs2(half, 0);
    39     cout << ans << endl;
    40 }

    IDA*

    估价函数+迭代加深

    若当前深度+未来估价>深度限制,立即回溯

  • 相关阅读:
    js的alert乱码问题
    (6)select语句
    (5)视图
    (4)索引
    (3)操作数据库
    (2)MySQL数据类型
    (1)MySQL概述
    RocketMQ安装使用
    uniapp打包h5
    面试必问 如何保证缓存与数据库的一致性
  • 原文地址:https://www.cnblogs.com/universeplayer/p/10508598.html
Copyright © 2011-2022 走看看