DFS之搜索顺序与剪枝

搜索顺序:

1.https://www.acwing.com/problem/content/1119/

首先,我们考虑一个贪心:

假如说A的倒数K个字符恰好与B的前K个字符重合,那么我们就连接。

也就是说我们一旦匹配就直接相连而不是继续找更长的重合的一段子串。

因此,我们可以先预处理出任意两个字符串重叠的部分,接下来就是DFS了:

AC代码:

#include<bits/stdc++.h>
using namespace std;
int n;
int g[100][100];//i的尾与j的头重叠的最小长度
string w[100];
int u[1000];
int ans;
void dfs(string dd,int last){ans=max(ans,(int)dd.size());u[last]++;for(int i=1;i<=n;i++){if(g[last][i]&&u[i]<2){dfs(dd+w[i].substr(g[last][i]),i);}}u[last]--;
}
int main(){cin>>n;for(int i=1;i<=n;i++) cin>>w[i];char start;cin>>start;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){//if(i==j) continue;for(int k=1;k<min(w[i].size(),w[j].size());k++){if(w[i].substr(w[i].size()-k)==w[j].substr(0,k)){g[i][j]=k;break;}}}}for(int i=1;i<=n;i++){if(w[i][0]==start){dfs(w[i],i);}}cout<<ans;
}

2.https://www.acwing.com/problem/content/1120/

首先,数据范围小,直接考虑爆搜。

那么选什么搜索顺序?我们按照每一个“桶”里放什么元素来DFS。

具体的,我们先看看第一个桶里放什么,当然存在某个时刻,第一个桶再也放不下所有东西了,于是我们就再开一个桶。

这里存在一个选择:当现在的桶还可以放东西时,是否还有必要再开一个桶?

答案是否定的,因为假如再开一桶,把那个东西放到上一个桶中一定也是合法的,因此答案不会更优。

同时注意我们选取东西不是DFS排列而是组合(因此规定从小到大)。

AC代码:

#include<bits/stdc++.h>
using namespace std;
int n;
int a[1010];
int ans=20;
int group[20][20];
int gcd(int a, int b)  // 欧几里得算法
{return b ? gcd(b, a % b) : a;
}
int check(int u,int j,int cnt1){for(int i=1;i<=cnt1;i++){if(gcd(a[group[u][i]],a[j])!=1) return 0;}return 1;
}
int vis[100];
void dfs(int u,int cnt,int start,int cnt1){if(u>=ans) return;if(cnt==n){ans=u;return;}int f=-1;for(int i=start+1;i<=n;i++){if(vis[i]==0&&check(u,i,cnt1)){f=1;vis[i]=1;cnt1++;group[u][cnt1]=i;dfs(u,cnt+1,i,cnt1);cnt1--;vis[i]=0;}}if(f==-1){dfs(u+1,cnt,0,0);}}
int main(){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];dfs(1,0,0,0);cout<<ans;
}

剪枝:

1.https://www.acwing.com/problem/content/167/

枚举每只猫放哪个车即可。

#include<bits/stdc++.h>
using namespace std;
int c[100],n,w;
int ans=20;
int sum[10010];
void dfs(int u,int k){if(k>=ans) return;if(u==n+1){ans=k;return;}for(int i=0;i<k;i++){if(sum[i]+c[u]<=w){sum[i]+=c[u];dfs(u+1,k);sum[i]-=c[u];}}sum[k]=c[u];dfs(u+1,k+1);sum[k]=0;
}
int main(){cin>>n>>w;for(int i=1;i<=n;i++) cin>>c[i];sort(c+1,c+n+1);reverse(c+1,c+n+1);dfs(1,0);cout<<ans<<endl;
}

2.https://www.acwing.com/problem/content/168/

总思路:随意选空格子,看是否可以填。

考虑剪枝:

1。优化搜索顺序:优先选限制多的

2.可行性剪枝:不能与行列以及九宫格重。

3.位运算加速:通过011100.....等九位01串来表示可行状态,求交集即可得到可行方案。

#include<bits/stdc++.h>
using namespace std;
const int N = 9, M = 1 << N;
int ones[M], cmap[M];
int row[N], col[N], cell[3][3];
char str[100];
void init()//一开始都可以选
{for (int i = 0; i < N; i ++ )row[i] = col[i] = (1 << N) - 1;for (int i = 0; i < 3; i ++ )for (int j = 0; j < 3; j ++ )cell[i][j] = (1 << N) - 1;
}void draw(int x, int y, int t, bool is_set)
{if (is_set) str[x * N + y] = '1' + t;else str[x * N + y] = '.';int v = 1 << t;if (!is_set) v = -v;row[x] -= v;col[y] -= v;cell[x / 3][y / 3] -= v;
}int lowbit(int x)
{return x & -x;
}int get(int x, int y)
{return row[x] & col[y] & cell[x / 3][y / 3];
}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 = cmap[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 ++ ) cmap[1 << i] = i;for (int i = 0; i < 1 << N; i ++ )for (int j = 0; j < N; j ++ )ones[i] += i >> j & 1;//处理i有多少1while (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);//进行跟新}else cnt ++ ;dfs(cnt);puts(str);}
}

3.https://www.acwing.com/problem/content/169/

整体思路:

先从小到大枚举木棒的长度,然后就是暴力DFS了。

考虑剪枝:

1.长度是sum的约数。

2.先枚举较长的木棍。

3.枚举组合数(下标从小到大)

4.木棒1失败,那么与它等长的也失败。

5.当前的第一个木棍失败,那么就直接回溯:

证明:假如3是某一个棒的第一个失败了,那么它一定存在在其他木棒中(假设4),那么木棒4中3的位置一定可以移到第一位,然后把棒4与3交换一下位置即可得出矛盾。

6.当前的最后一个木棍失败,那么就直接回溯:

证明:假如3是某一个棒的最后一个失败了,那么考虑把它放在其他木棒中(假设4),那么刚才那个木棒的填充最后一个的与放在4的那个交换一下一定也可,这也与前矛盾。

#include<bits/stdc++.h>
using namespace std;
const int N = 70;
int n;
int w[N];
int sum, length;
bool st[N];
bool dfs(int u, int cur, int start)//u:当前枚举的木棒cur:当前枚举的木棒的位置start:下标开始
{if (u * length == sum) return true;if (cur == length) return dfs(u + 1, 0, 0);for (int i = start; i < n; i ++ ){if (st[i] || cur + w[i] > length) continue;st[i] = true;if (dfs(u, cur + w[i], i + 1)) return true;st[i] = false;if (!cur || cur + w[i] == length) return false;//开头和结尾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];}sort(w, w + n);reverse(w, w + n);//顺序优化length = 1;while (true){if (sum % length == 0 && dfs(0, 0, 0)){cout << length << endl;break;}length ++ ;}}
}

4.https://www.acwing.com/problem/content/170/

枚举每一层DFS即可,下面考虑剪枝:

我们记最上层为1,可以得到:

S={R_{m}^{2}}+\sum_{i=1}^{m}2*R_{i}^{}*H_{i}^{}

N=\sum_{i=1}^{m}R_i{}^{2}*H_{i}

1.我们自底向上搜,同时先枚举R(因为平方)(从大到小)

2.我们再考虑可行性剪枝:

由于N-V\geqslant R_{u}^{2}*h_{u}

我们可以得到枚举的范围:

u\leqslant R_{u}\leqslant min(N-V,R_{u+1}-1)

u\leqslant H_{u}\leqslant min(H_{u+1}-1,N-V/R_{u}^{2})

同时我们可以估计前几层的最小S/V:

于是需要满足:

V+minV(u)\leqslant n     S+minS(u)\leqslant ans

最后我们考虑对公式的放缩:

S_{1\rightarrow u}=2/R_{u+1}*\sum_{k=1}^{u}R_{k}*H_{k}*R_{u+1}> 2/R_{u+1}*(N-V)

于是我们把这个估计的加上现在的S判断与ans的大小关系即可。

AC代码:

#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 -- )for (int h = min(H[u + 1] - 1, (n - v) / r / r); h >= u; h -- ){int t = 0;if (u == m) t = r * r;R[u] = r, H[u] = 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) ans = 0;cout << ans << endl;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【学习方法】高效学习因素 ② ( 学习动机 | 内在学习动机 | 外在学习动机 | 外在学习动机的调整方向 | 保护学习兴趣 | 高考竞争分析 )

文章目录 一、高效学习的其它因素 - 学习动机1、学习动机2、内在学习动机3、外在学习动机4、外在学习动机的问题所在5、外在学习动机的调整方向6、保护学习兴趣7、高考竞争分析 上一篇博客 【学习方法】高效学习因素 ① ( 开始学习 | 高效学习因素五大因素 | 高效学习公式 - 学…

unplugin-vue-components 插件配置 忽略 部分目录下的组件自动导入

背景 vue3 项目 为了省略 第三方库ui 组件 全局组件的注册代码&#xff0c;使用了 unplugin-vue-components 插件 原理 组件识别 在编译阶段&#xff0c;unplugin-vue-components 会扫描 Vue 单文件组件&#xff08;.vue 文件&#xff09;的模板部分&#xff0c;识别出所有使…

day31

3.9 信号量集 1> 原理图 信号量集主要完成多个进程之间同步问题 2> 信号量集的API函数接口 1、创建用于生成消息队列的钥匙#include <sys/types.h>#include <sys/ipc.h>key_t ftok(const char *pathname, int proj_id);功能&#xff1a;通过给定的文件路径…

你也觉得FOTA升级难吗?这份详细教程让你自信升级!

前言&#xff1a; 我经常在各个讨论群里看到有合宙Air780EP的用户说&#xff1a; FOTA远程升级有点难呀~一步错后面就得重新来了&#xff0c;有没有大佬给个教程啊&#xff1f; 用户提需求了&#xff0c;那我们肯定要满足啊&#xff0c;就连夜赶了一篇 在整理这篇文章之前&…

掌握 LINQ:通过示例解释 C# 中强大的 LINQ的集运算

文章目录 集运算符原理实战示例1. Union2. Intersect3. Except4. ExceptWith5. Concat6. Distinct 注意事项总结 在C#中&#xff0c;LINQ&#xff08;Language Integrated Query&#xff09;提供了丰富的集合操作功能&#xff0c;使得对集合数据进行查询、过滤、排序等操作变得…

删除有序数组中的重复项(LeetCode)

题目 给你一个 升序排列 的数组 &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 中唯一元素的个数。 考虑 的唯一元素的数量为 &#xff0c;你需要做以下事情确…

CVE-2023-1313

开启靶场 url访问/install来运行安装 http://eci-2ze0wqx38em0qticuhug.cloudeci1.ichunqiu.com/install/ 得知其用户和密码为admin 登录 查找文件上传位置 上传一句话木马文件 <?php echo phpinfo();eval($_POST[flw]);?> 下载查看上传木马路径 复制路径 /storag…

代理IP如何助力品牌保护?

品牌是企业非常重要的无形资产&#xff0c;代表着一个公司、一个产品或服务的价值、信誉和形象。在竞争激烈的市场中&#xff0c;一个强有力的品牌可以帮助公司吸引更多的客户、提高销售、提高客户满意度和忠诚度&#xff0c;还可以帮助公司建立和维护其声誉、增强其企业形象&a…

单词拆分——LeetCode

139.单词拆分 题目 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。 注意&#xff1a;不要求字典中出现的单词全部都使用&#xff0c;并且字典中的单词可以重复使用 示例 1&#xff1a; 输入: s &qu…

数据结构实验:树和二叉树(附c++源码:实现树有关算法)

目录 一、实验目的 二、问题分析及数据结构设计 三、算法设计&#xff08;伪代码表示&#xff09; 1. 输入字符序列 创建二叉链表 2. 递归前序遍历 3. 递归中序遍历 4. 递归后序遍历 5. 非递归前序遍历 6. 非递归中序遍历 7. 非递归后序遍历 8. 层次遍历 9. 求二叉…

【AI】关于AI和手机

2011 年至2015 年期间&#xff0c;全球智能手机出货量年增长率均超过两位数&#xff0c;显示出强劲的市场需 求和快速扩张趋势。然而&#xff0c;自2016 年起&#xff0c;全球智能手机用户数量趋于饱和&#xff0c;换机周期也逐 渐变长&#xff0c;市场进入存量替换阶段&#x…

Qt/C++最新地图组件发布/历时半年重构/同时支持各种地图内核/包括百度高德腾讯天地图

一、前言说明 最近花了半年时间&#xff0c;专门重构了整个地图组件&#xff0c;之前写的比较粗糙&#xff0c;有点为了完成功能而做的&#xff0c;没有考虑太多拓展性和易用性。这套地图自检这几年大量的实际项目和用户使用下来&#xff0c;反馈了不少很好的建议和意见&#…

PXE 批量安装Linux系统

目录 一、 实验环境准备 1、一台红帽版本7的主机 2、开启主机图形 3、配置网络可用 4、关闭VMware dhcp 功能 ​编辑​编辑 5、配置好本地仓库&#xff0c;方便后续下载 二、配置kickstart自动安装脚本的工具 1、 安装图形化生成kickstart自动安装脚本的工具 2、启动图…

2.MySQL库的操作

创建数据库 创建数据库的代码&#xff1a; CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [,create_specification] ...];​create_specification:[DEFAULT] CHARACTER SET charset_name[DEFAULT] COLLATE collation_name 说明&#xff1a; 大写的表示关键…

【隐私保护】无证书签名方案(CLS)

一、CLS方案提出的背景 无证书签名方案&#xff08;Certificateless Signature Scheme, CLS&#xff09;是一种旨在结合公钥基础设施&#xff08;PKI&#xff09;和基于身份的加密&#xff08;IBE&#xff09;的优点&#xff0c;同时避免它们缺点的加密技术。 CLS方案的主要目标…

【网络安全渗透测试零基础入门必知必会】之什么是文件包含漏洞分类(非常详细)零基础入门到精通,收藏这一篇就够了

一、前言 这是大白给粉丝盆友们整理的网络安全渗透测试入门阶段文件包含渗透与防御第1篇。 本文主要讲解什么是文件包含漏洞、本地文件包含漏洞 喜欢的朋友们&#xff0c;记得给大白点赞支持和收藏一下&#xff0c;关注我&#xff0c;学习黑客技术。 一、什么是文件包含漏洞…

【HarmonyOS NEXT星河版开发学习】小型测试案例07-弹性布局小练习

个人主页→VON 收录专栏→鸿蒙开发小型案例总结​​​​​ 基础语法部分会发布于github 和 gitee上面&#xff08;暂未发布&#xff09; 前言 在鸿蒙&#xff08;HarmonyOS&#xff09;开发中&#xff0c;Flex布局是一种非常有用的布局方式&#xff0c;它允许开发者创建灵活且响…

Spring Boot实战:拦截器

一.拦截器快速入门 1.1了解拦截器 什么是拦截器&#xff1a; 概念 &#xff1a;拦截器是Spring框架提供的核⼼功能之⼀, 主要⽤来拦截⽤⼾的请求, 在指定⽅法前后, 根据业务需要执⾏预先设定的代码。 也就是说, 允许开发⼈员提前预定义⼀些逻辑, 在⽤⼾的请求响应前后执⾏. 也…

ThinkPHP6与金仓数据库(Kingbase)集成:模型查询的解决方案

摘要&#xff1a; ThinkPHP6是一款流行的PHP框架&#xff0c;支持多种数据库。然而&#xff0c;对于金仓数据库&#xff08;Kingbase&#xff09;这种相对小众的数据库系统&#xff0c;开发者在使用ThinkPHP6进行模型查询时可能会遇到一些兼容性问题。本文将提供一种解决方案&a…

仿推特社区源码修复版,含pc端和H5端,可以封装成app

简介&#xff1a; 新鲜出炉的仿推特社区源码修复版&#xff0c;含pc端和H5端&#xff0c;可以封装成app。这玩意绝对可以算是精品代码了。 手机h5端可以封装成软件也不错的。 推特的风格还是不错的&#xff0c;不然世界首富马斯克也不会花费440亿美金收购它了。 阅览&#…