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

news2024/11/18 1:36:51

剪枝与优化的方法

1.优化搜索顺序

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

2.排除等效冗余

3.可行性剪枝

4.最优性剪枝

5.记忆化搜索(DP)

1.小猫爬山

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

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

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

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

#include<bits/stdc++.h>
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<k;i++)
    if(group[i]+w[u]<=W)//可行性剪枝
    {
        group[i]+=w[u];//该组加上他
        dfs(u+1,k);//继续处理下一个数,组数不变
        group[i]-=w[u];//恢复现场
    }
    //新开一个组
   group[k]+=w[u];//该组加上他
   dfs(u+1,k+1);//继续处理下一组,组数加一
   group[k]-=w[u];//恢复现场
}
int main()
{
   cin>>n>>W;
   for(int i=0;i<n;i++) cin>>w[i];
   //下面两步是优化搜索顺序
   sort(w,w+n);
   //从大到小排序
   reverse(w,w+n);
   dfs(0,0);
   cout<<ans<<endl;
   return 0;
}

2.数独 

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

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

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

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

#include<bits/stdc++.h>
using namespace std;
const int N=9,M=1<<N;
int ones[M],mark[M];
char str[100];
int row[N],col[N],cell[3][3];
void init()//赋予状态
{
    //一开始所有行列九宫格都没数字
    for(int i=0;i<N;i++) col[i]=row[i]=M-1;
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
          cell[i][j]=M-1;
}
void draw(int x,int y,int t,bool is_set)//用于在str上画数字
{
    if(is_set) str[x*N+y]='1'+t;//假如是要画数字的,则在str上赋值
    else str[x*N+y]='.';//反之是空位的
    int v=1<<t;//用来获取该数字的二进制
    if(!is_set) v=-v;//假如是空位,则为-v
    //-=v说明数字t在行和列和九宫格都用过了
    row[x]-=v;
    col[y]-=v;
    cell[x/3][y/3]-=v;
}
int get(int x,int y)//用来获取行和列和九宫格没出现过的数
{
    return row[x]&col[y]&cell[x/3][y/3];
}
int lowbit(int x)//用来获取某个数字第一个1
{
    return x&-x;
}
bool dfs(int cnt)
{
    if(!cnt) return true;//假如已经弄完了
    int minv=10;
    int x,y;
    for(int i=0;i<N;i++)//找某个没填的位置的所用的数字的最小
        for(int j=0;j<N;j++)
        if(str[i*N+j]=='.')//假如是要填数学的
        {
           int state=get(i,j);//获取这个位置能填的数字
           if(ones[state]<minv)
           {
               minv=ones[state];
               x=i,y=j;
           }
        }
    int state=get(x,y);//这个状态是所有空格中能填的数字的最少
    for(int i=state;i;i-=lowbit(i))//开始填这个状态能填的数
    {
        int t=mark[lowbit(i)];//获取该数字是什么
        draw(x,y,t,true);//填上这个数字
        if(dfs(cnt-1)) return true;
        draw(x,y,t,false);//恢复现场
    }
    return false;
}
int main()
{
    //初始化
    for(int i=0;i<N;i++) mark[1<<i]=i;//用来算2的n次方
    for(int i=0;i<1<<N;i++)//用来求某个数i的个数
        for(int j=0;j<N;j++)
           ones[i]+=i>>j&1;
   while(cin>>str,str[0]!='e')
   {
       init();//从新赋予状态
       int cnt=0;
      for(int i=0,k=0;i<N;i++)
       for(int j=0;j<N;j++,k++)
        if(str[k]!='.')//假如某个位置是数学
          {
              int t=str[k]-'1';//转换成数字
              draw(i,j,t,true);//在str上标记一下
          }
        else cnt++;//反之是要填的数
        dfs(cnt);//dfs一遍要填的所有数
         puts(str);//输出填完后的str
   }
   return 0;
}

3.木棒

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

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

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

剪枝3.排除等效元素

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

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

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

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

#include<bits/stdc++.h>
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;i<n;i++)
    {
        if(st[i]) continue;//假如用过
        if(s+w[i]>len) 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&&w[j]==w[i]) j++;
        i=j-1;
    }
    return false;//反之不符合
}
int main()
{
   while(cin>>n,n)
   {
       memset(st,0,sizeof st);//清空上一层状态
       sum=0;
       for(int i=0;i<n;i++) cin>>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<<len<<endl;
               break;
           }
           len++;
           if(len>sum) break;//假如已经超了
       }
   }
   return 0;
}

4.生日蛋糕 

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

 

#include<bits/stdc++.h>
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<<ans<<endl;//假如有方案
   else cout<<0<<endl;//假如没方案输出0
   return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/563466.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《操作系统》期末最全复习题及解析

文章目录 选择题填空题简答题程序题综合题1.银行家算法2.页面置换算法3.进程调度算法4.磁盘调度算法5.求物理/逻辑地址6.分页存储管理7.可变分区分配算法 选择题 若信号量S的初值为2&#xff0c;且有3个进程共享此信号量&#xff0c;则S的取值范围是&#xff08;B &#xff09;…

单词长度统计,统计数据放入列表

输入一段英文计算每个单词长度&#xff0c;统计不含非英文字符&#xff0c;列表输出。 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅是基础那么简单…… 地址…

AI与税务管理:新技术带来的新机遇和新挑战

本文作者&#xff1a;王伊琳 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是指由计算机系统或机器人模拟人类智能的过程和结果&#xff0c;包括感知、理解、学习、推理、决策等能力。近年来&#xff0c;随着计算机技术、互联网平台、大数据分析等的…

AI工具 ChatGPT-4 vs Google Bard , PostgreSQL 开发者会pick谁?

在人工智能 (AI) 进步的快节奏世界中&#xff0c;开发人员正在寻找最高效和突破性的解决方案来加快和提高他们的工作质量。对于 PostgreSQL 开发人员来说&#xff0c;选择理想的 AI 支持的工具以最专业的方式解决他们的查询至关重要。 近年来&#xff0c;人工智能工具的普及率…

Redis如何做到内存高效利用?过期key删除术解析!

大家好&#xff0c;我是小米&#xff0c;一个热衷于分享技术的小伙伴。今天我要和大家探讨一个关于 Redis 的话题&#xff1a;删除过期key。在使用 Redis 进行数据存储和缓存时&#xff0c;我们经常会遇到过期数据的处理问题。接下来&#xff0c;我将为大家介绍为什么要删除过期…

很多人都在考的PMP认证到底有什么用?考试内容难不难?

工作几年之后&#xff0c;很多人都会选择提升自己&#xff0c;从而达到升职加薪的目的&#xff0c;而除了学习专业的技能外&#xff0c;考取一份含金量高的证书&#xff0c;也是非常重要的途径&#xff0c;PMP的证书在业界内的名气很大&#xff0c;该证书是由美国项目管理协会&…

JSP工作原理

一、JSP--一门远古的技术 JSP全称是Java Server Pages&#xff0c;它和servle技术一样&#xff0c;都是SUN公司定义的一种用于开发动态web资源的技术。 JSP这门技术的最大特点在于&#xff0c;写JSP就行html&#xff0c;但是html只能提供静态数据&#xff0c;而Jsp技术可以嵌套…

【C++】容器篇(二)——List的基本概述以及模拟实现

前言&#xff1a; 在上期&#xff0c;我们学习了STL库中的第一个容器--vector &#xff0c;今天我将给大家介绍的是 库中的另外一个容器--List。其实&#xff0c;有了之前学习 vector 的知识&#xff0c;对于List 的学习成本就很低了。 目录 &#xff08;一&#xff09;基本介…

Windows古老Bug损坏SSD/HDD,Win7到Win11全遭殃

去年微软确认了 Windows 12 将在2024年发布&#xff0c;Win11 的更新变为了小的功能更新。 今年3月 Win11 Moment 2 带来了包括任务栏在内的小更新&#xff0c;Moment 3 在这两天就会出来。 Win11 的更新明显放缓&#xff0c;也让用户松了口气。 因为自古以来 Windows 更新大…

5.7 文件I/O(文件IO打开和关闭)

目录 文件描述符 open open-示例1 open-示例2 close 笔记 文件描述符 每个打开的文件都对应一个文件描述符。 文件描述符是一个非负整数。Linux为程序中每个打开的文件分配一个文件描述符。 文件描述符从0开始分配&#xff0c;依次递增。 文件IO操作通过文件描述符来完…

【多线程】常见面试题

1.你知道线程与进程的区别吗&#xff1f; 进程是系统进行资源分配和调度的一个独立单位&#xff0c;线程是程序执行的最小单位&#xff0c;一个进程必然有一条线程&#xff08;主线程&#xff09;。进程有自己的内存地址空间&#xff0c;线程只独享指令流执行的必要资源&#…

毫米波雷达信号处理中的静止目标(静态杂波)滤除问题

说明 杂波及其消除是雷达信号处理中的一个很重要的话题&#xff0c;不过对于车载毫米波雷达&#xff0c;考虑到其应用场景和作用范围&#xff0c;关于杂波我们需要考虑的东西其实并没有比如预警雷达、机载SAR雷达等那么多。特别是车载4D雷达的出现&#xff0c;杂波这个概念已经…

【Linux系统编程(文件编程)】之创建、打开文件

文章目录 一、前言二、打开文件、创建文件1. man手册使用起来2. open函数参数 三、文件权限四、打开、创建 的代码示例五、文件创建、打开的补充O_EXCLO_APPENDO_TRUNCcreat创建文件函数 一、前言 linux下&#xff0c;一切皆文件。学好对文件的操作是很重要的&#xff0c;会在…

pytorch:nn.ModuleList和nn.Sequential、list的用法以及区别

文章目录 在构建网络的时候&#xff0c;pytorch有一些基础概念很重要&#xff0c;比如nn.Module&#xff0c;nn.ModuleList&#xff0c;nn.Sequential&#xff0c;这些类我们称为为容器&#xff08;containers&#xff09;&#xff0c;可参考containers。本文中我们主要学习nn.…

3D模型渲染引擎6大特点解读:助力AR/VR呈现惊叹的视觉效果!

一、用于桌面、移动和 AR/VR 应用程序的2D和3D图形引擎 HOOPS Visualize是一个3D图形SDK&#xff0c;可以快速开发高性能、跨平台的工程应用程序。主要特点包括&#xff1a; HOOPS Visualize的基石是图形内核&#xff0c;这是一种功能齐全、以工程为中心的场景图形技术&#…

项目实战(cloud)--配置中心Config(码云来做一个配置中心)

服务的拆分原则&#xff1a; 单体应用向微服的一个改造&#xff1a; 搭建一个聚合项目 创建一个maven项目 父项目 pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"…

uCOSii信号量

uCOSii信号量 主要用来测试使用uCOSii“创建信号量,发送信号量&#xff0c;接收信号量,删除信号量”。 学习uCOSii一定要先了解os_cfg.h文件。 信号量管理函数如下&#xff1a; OSSemAccept() 无条件地等待请求一个信号量函数,中断服务子程序只能用OSSemAccept()而不能用OS…

Docker介绍、常用命令、项目部署

什么是Docker 简单说&#xff1a;Docker就是一个虚拟机&#xff0c;专业说&#xff1a;它是一个开源的容器平台。它和我们常用的VMware有很多相似的地方。 名词解释 镜像/images 由本体打包出来的文件。并不是文件本身&#xff0c;但是具有该文件的功能。举个不太贴切的例子&…

离线安装python、pip和python的第三方库

1.安装python3 1.1下载python3 安装python3的网址为点击这里 选择想要下载的对应版本进行下载&#xff0c;这里使用的是63位的Windows系统&#xff0c;因此下载的选的是&#xff1a; 下载后如图&#xff1a; python-3.7.9-amd64.exe是python3的安装程序 1.2安装python3 1…