acwing提高--DFS之剪枝与优化

剪枝与优化的方法

1.优化搜索顺序

   大部分情况下,我们应该优先搜索分支较少的节点

2.排除等效冗余

3.可行性剪枝

4.最优性剪枝

5.记忆化搜索(DP)

1.小猫爬山

 题目https://www.acwing.com/problem/content/description/167/

1.优化搜索顺序-》从大到小排序进行搜索

2.可行性剪枝-》假如该组总和+当前数则不可行

3.最优性剪枝-》因为要答案最小,假如搜索过程中已经大于我的答案了,说明后面的搜索都没用

#include
using namespace std;
const int N=20;
int n,W;
int w[N],ans=N;
int group[N];
void dfs(int u,int k)//u是第几个数,k是有多少组
{
    if(k>=ans) return;//最优性剪枝
    if(u==n)//假如搜完了所有点
    {
        ans=k;
        return;
    }
   for(int i=0;i>n>>W;
   for(int i=0;i>w[i];
   //下面两步是优化搜索顺序
   sort(w,w+n);
   //从大到小排序
   reverse(w,w+n);
   dfs(0,0);
   cout<

2.数独 

题目 https://www.acwing.com/problem/content/description/168/

1.优化搜索顺序->选择分支较少的点

2.可行性剪枝-》不能与行、列和九宫格重复

3.最优性剪枝-》位运算优化,用来判断那个位置能填的数有哪些

#include
using namespace std;
const int N=9,M=1<>j&1;
   while(cin>>str,str[0]!='e')
   {
       init();//从新赋予状态
       int cnt=0;
      for(int i=0,k=0;i

3.木棒

题目icon-default.png?t=N4N7https://www.acwing.com/problem/content/169/

剪枝1.最优性剪枝-》只有当长度能被总和整除时才合法

剪枝2.优化搜索顺序-》从大到小枚举

剪枝3.排除等效元素

        3-1  按照组合的方式枚举

        3-2  假如目前的木棍加到当前组失败了,则直接略过后面长度相等的木棍

        3-3  假如木棍第一根就失败了,则一定会失败

       3-4  假如木棍最后一根失败了,则一定会失败

#include
using namespace std;
const int N=70;
int n,len,sum;
int w[N];
bool st[N];
bool dfs(int u,int s,int start)//u表示有第几组,s表示该组的总和,start表示从第几个开始搜
{
    if(u*len==sum) return true;//假如组数乘长度已经等于总和了,说明这种长度符合
    if(s==len) return dfs(u+1,0,0);//假如该组已经满了,则新开一组继续搜
    //剪枝3-1,i从start开始
    for(int i=start;ilen) continue;//可行性剪枝
        st[i]=true;//标记用过
        if(dfs(u,s+w[i],i+1)) return true;//则放进该组里,继续搜索
        st[i]=false;//回溯,恢复现场
        //剪枝3-3
        if(!s) return false;
        //剪枝3-4
        if(s+w[i]==len) return false;
        //剪枝3-2
        int j=i;
        while(j>n,n)
   {
       memset(st,0,sizeof st);//清空上一层状态
       sum=0;
       for(int i=0;i>w[i],sum+=w[i];
       //剪枝2,优化搜索顺序
       sort(w,w+n);
       reverse(w,w+n);
       len=w[0];
       //最大一组就是自己sum
       while(1)
       {
           //剪枝1
           if(sum%len==0&&dfs(0,0,0))//假如这个长度符合
           {
               cout<sum) break;//假如已经超了
       }
   }
   return 0;
}

4.生日蛋糕 

题目icon-default.png?t=N4N7http://ybt.ssoier.cn:8088/problem_show.php?pid=1441

acwing提高--DFS之剪枝与优化_第1张图片

 

#include
using namespace std;
const int N=25,INF=1e9;
int n,m;
int minv[N],mins[N];
int R[N],H[N];
int ans=INF;
void dfs(int u,int v,int s)
{
    if(v+minv[u]>n) return;//假如体积已经大于最大体积了
    if(s+mins[u]>=ans) return;//假如已经大于等于当前答案了,后面在做没意义了
    if(s+2*(n-v)/R[u+1]>=ans) return;//推理优化
    if(!u)//假如搜到了最后一个数
    {
        if(v==n) ans=s;//假如体积刚好符合,则更新一下最小值
        return;
    }
    for(int r=min(R[u+1]-1,(int)sqrt(n-v));r>=u;r--)//枚举合法的r
        for(int h=min(H[u+1]-1,(n-v)/r/r);h>=u;h--)//枚举合法的h
        {
           int t=0;
           if(u==m) t=r*r;//表面积的增加量
           R[u]=r,H[u]=h;//该点的r是r,h是h
           dfs(u-1,v+r*r*h,s+2*r*h+t);//处理下一步
        }
}
int main()
{
   cin>>n>>m;
   for(int i=1;i<=m;i++)
   {
       minv[i]=minv[i-1]+i*i*i;
       mins[i]=mins[i-1]+2*i*i;
   }
   R[m+1]=H[m+1]=INF;
   dfs(m,0,0);//从底往上搜索
   if(ans!=INF)  cout<

你可能感兴趣的:(acwing提高,搜索,深度优先,算法)