这题听说是道十分经典的剪枝算的题目,不要问我剪枝是什么,我也不知道,反正我只知道用到了深度搜索

我参考了好多资料才悟懂,然后我发现网上的那些大神原理讲的很明白,但代码没多少注释,看的很懵X,于是我抄起VS写了个详细注释版,真的很详细,史上最详细,全宇宙最详细,就这么自信,不信你看,看不懂你咬我。

/*--------------------------------------------
* 剪枝算法经典例题Sticks详细注释版
*---------------------------------------------*/ #include <iostream> using namespace std; //某根木棍被使用过就设置标志位为1,没使用过则设置标志位为0
#define USED 1
#define UNUSED 0
#define MAXSIZE 64 //定义木棍结构体
typedef struct Stick
{
int length;//每根木棍的长度
int mark;//标志位,记录是否被使用过
}Sticks[MAXSIZE]; //虽然程序中使用全局变量是不好的习惯,但做题who care
int n;//未拼接时的总木棒数
int g;//拼接好后的木棒数
int len;//满足要求的拼接后的木棒的长度
Sticks sticks;//定义一个木棒集合,记录未拼接时各木棒的信息 //定义一个冒泡排序算法,从大到小排序
void BubbleSort(Sticks *a,int num)
{
int i,j;
int temp;//交换时用的中间变量
for (i = 0;i<num-1;i++)
{
for (j = 0;j<num-1;j++)
{
if ((*a)[j].length<(*a)[j+1].length)
{
//交换
temp = (*a)[j].length;
(*a)[j].length = (*a)[j+1].length;
(*a)[j+1].length = temp;
}
}
}
} /*剪枝函数,深度搜索
*总共三个参数,nowLen表示现在拼接成的木棒的长度,
*nowGet表示现在拼接成的木棒的总数,此值若等于之前的g则说明找到符合要求的木棒长,
*cnt表示拼接过程中查找剩下符合要求的木棒从哪个下标开始查找,当cnt大于n时说明没有符合要求的拼接方法
*该函数返回1代表找到了,0代表没有找到符合要求的*/
int DFS(int nowLen,int nowGet,int cnt)
{
if (cnt>=n) return 0;//找的下标都超了,肯定不满足
if (nowGet == g) return 1;//如果这个长度下获取的总个数与g相等说明符合条件
int i; //开始遍历查找
for (i = cnt;i<n;i++)
{
if (sticks[i].mark==UNUSED)
{
//当找到的一组木棒恰好能拼接成需要的长度时
if (nowLen+sticks[i].length == len)
{
sticks[i].mark = USED;//设置这个木棒已使用过
//这组满足,开始下一组寻找
if (DFS(0,nowGet+1,nowGet)==1)
{
//递归,直到最后每一组都满足需要的长度时说明这个长度可行
return 1;
}
sticks[i].mark = UNUSED;//解除使用
return 0;
}
//当找到的一组木棒还小于拼接成需要的长度时
else if(nowLen+sticks[i].length < len)
{
sticks[i].mark = USED;//设置这个木棒已使用过
if(DFS(nowLen+sticks[i].length,nowGet,i+1)==1)
{
//同样递归,这里说明一下i+1,这个意思是从i+1下标开始寻找要使这组木棒满足要求的木棒
return 1;
}
sticks[i].mark = UNUSED;//解除使用
//下面这句表示如果当前搜索时,前边的长度为0,而第一根没有成功的使用,
//说明第一根始终要被废弃,所以这种组合必定不会成功
//此处的剪枝必须有,因为这里的剪枝会节省很多的无用搜索,
//缺少这一句超时
if (nowLen == 0) return 0;
//下面这句是指如果有一根木棒加上去已经知道不满足要求了,则与它相同长度的木棒都可以跳过
for ( ;sticks[i].length==sticks[i+1].length&&i+1<n;i++);
}
} } return 0;
} int main()
{
int i;
int sum;//木棒的总长 //用户输入每组的木棒数
while(cin>>n,n)
{
//木棒一开始都初始化为未使用过的
for (i = 0;i<MAXSIZE;i++)
{
sticks[i].mark = UNUSED;
}
sum = 0;
for (i = 0;i<n;i++)
{
cin>>sticks[i].length;
sum+=sticks[i].length;
} //从大到小排序
BubbleSort(&sticks,n);
for (len = sticks[0].length;len<=sum;len++)
{
if (sum%len!=0) continue;//最后选的木棒长度一定是能被总木棒长整除的 g = sum/len;//拼接的后的木棒数
//剪枝,满足要求退出循环
if(DFS(0,0,0))
{
break;
}
}
//输出满足要求的木棒长
cout << len<<endl;
} return 0;
}

经典剪枝算法的例题——Sticks详细注释版的更多相关文章

  1. 【强连通分量】 Kosaraju和Tarjan算法 (标准模板+详细注释)

    codevs 题意:求最大强连通分量的大小以及所包含的顶点有哪些 Tarjan算法 #include<iostream> #include<queue> #include< ...

  2. SSM+shiro,所有配置文件,详细注释版,自用

    spring配置文件applicationContext.xml,放在resources下 <?xml version="1.0" encoding="UTF-8& ...

  3. SSM+shiro及相关插件的整合maven所有依赖,详细注释版,自用,持续更新

    整合了SSM+shiro框架,slf4j+logback日志,及一些好用的插件PageHelper,mybatis-generator,Lombok,fastjson等等 <?xml versi ...

  4. DRF 简单使用(详细注释版)

    1.djangorestframework使用 下载安装 pip install djangorestframework ## djangorestframework pip install djan ...

  5. Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释

     原题链接   无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点:然后再把所有点遍历一遍 ...

  6. 【蓝桥杯/算法训练】Sticks 剪枝算法

    剪枝算法 大概理解是通过分析问题,发现一些判断条件,避免不必要的搜索.通常应用在DFS 和 BFS 搜索算法中:剪枝策略就是寻找过滤条件,提前减少不必要的搜索路径. 问题描述 George took ...

  7. 紫书 例题8-17 UVa 1609 (构造法)(详细注释)

    这道题用构造法, 就是自己依据题目想出一种可以得到解的方法, 没有什么规律可言, 只能根据题目本身来思考. 这道题的构造法比较复杂, 不知道刘汝佳是怎么想出来的, 我想的话肯定想不到. 具体思路紫书上 ...

  8. acm常见算法及例题

    转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题  初期:一.基本算法:     (1)枚举. (poj17 ...

  9. 【十大经典数据挖掘算法】AdaBoost

    [十大经典数据挖掘算法]系列 C4.5 K-Means SVM Apriori EM PageRank AdaBoost kNN Naïve Bayes CART 1. 集成学习 集成学习(ensem ...

随机推荐

  1. git注册到git管理远程仓库

    注册: ① 注册github网站:地址:https://github.com/,其中sign up 是注册,sign in是登录 (如果是用QQ邮箱的话,如果觉得收不到邮箱,可能是在垃圾箱哦) ② 之 ...

  2. docker部署rockermq集群(docker-compose版本)

    此处采用docker-compose部署 rockermq主主集群模式 创建相关文件夹 此处创建的文件一一对应docker-compose.yml文件中的映射文件夹,酌情创建,主要需要创建配置文件夹. ...

  3. day53:django:URL别名/反向解析&URL分发&命名空间&ORM多表操作修改/查询

    目录 1.URL别名&反向解析 2.URL分发&命名空间 3.ORM多表操作-修改 4.ORM多表操作-查询 4.1 基于对象的跨表查询 4.2 基于双下划线的跨表查询 4.3 聚合查 ...

  4. ribbon源码(6) Server

    Server 代表一个服务器信息. 内部有服务器地址(host).服务器端口(port).服务器dc(zone).是否存活标志(isAliveFlag).请求协议(scheme).是否可以提供服务(r ...

  5. redis实现计数器

    用redis实现计数器 社交产品业务里有很多统计计数的功能,比如: 用户: 总点赞数,关注数,粉丝数 帖子: 点赞数,评论数,热度 消息: 已读,未读,红点消息数 话题: 阅读数,帖子数,收藏数 统计 ...

  6. ftp自动上传下载同步工具 免费好用的ftp自动上传下载同步工具

    有时我们需要定时上传文件到FTP,可大多数FTP工具并不支持定时上传功能,这时我们就需要可以定时ftp上传的工具(服务器管理工具).它是一款功能强大的服务器集成管理器,包含win系统和linux系统的 ...

  7. 容器云平台No.2~kubeadm创建高可用集群v1.19.1

    通过kubernetes构建容器云平台第二篇,最近刚好官方发布了V1.19.0,本文就以最新版来介绍通过kubeadm安装高可用的kubernetes集群. 市面上安装k8s的工具很多,但是用于学习的 ...

  8. dubbo学习(五)注册中心zookeeper

    初识zookeeper 下载地址:https://archive.apache.org/dist/zookeeper/ 详细的ZooKeeper教程戳这里~ PS: 建议目前选择3.4的稳定版本进行使 ...

  9. Ribbon源码分析(一)-- RestTemplate 以及自定义负载均衡算法

    如果只是想看ribbon的自定义负载均衡配置,请查看: https://www.cnblogs.com/yangxiaohui227/p/13186004.html 注意: 1.RestTemplat ...

  10. Activiti工作流系统环境搭建

    一.创建Activiti工程,并导入Activiti包及数据库驱动包 二.用代码方式创建 流程引擎 1 @Test 2 public void createProcessEngineWithCode( ...