一、题目回顾

题目链接:Sticks

题意:给出一定数量的小木棒的长度,它是由等长的若干木棒随意砍断所得到的。对于给定的一组小木棒,请求出原始木棒的最小长度。

二、解题思路

  • DFS+剪枝
  • 本题剪枝不到一定火候将会TLE,只有完成一定的剪枝才能AC

本题,我将从我做这题的角度,将所思所想具体记录下来,详细的官版思想见我另一个题解

首先,看main函数:

int main()
{
while(scanf("%d",&n) && n){
int sum=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum += a[i]; //记录现在所有木棒的长度之和
}
sort(a+1,a+1+n,cmp); //将数组a中的元素从大到小排列
int len;
flag = 0;
//原木棒长度一定大于等于现在的任何一支木棒(即大于等于最长的木棒)
//原木棒长度一定小于等于现在所有木棒的长度之和
for(len=a[1];len<=sum;len++){ //a[1]为最长木棒的长度
if(sum%len==0){ //原木棒的根数一定是个整数
memset(vis,0,sizeof(vis));
dfs(len,0,n); //假设原木棒长度为len,要拼的原木棒已拼成的长度为0,还有n根木棒
if(flag==1){ //已经拼成功,就退出,因为要原木棒尽可能短
break;
}
}
}
printf("%d\n",len); //打印原木棒的长度
}
return 0;
}

做到这,我在思考,如果原木棒的根数大于1,那么在第一根原木棒拼完之后,我该如何确定第二根,第三根,…

【dfs形参的确定】

  • len  假设的原木棒的长度
  • now   现在拼的长度(在一根原木棒之内)
  • num     剩下的小木棒数目

再看dfs的代码:

void dfs(int len,int now,int num)		//预设的原木棒的长度  正在完成的木棒的长度  剩余的小木棒数量
{
if(num==0){
flag = 1;
return;
}
if(now==len) dfs(len,0,num);
for(int i=1;i<=n;i++){
if(!vis[i] && a[i]+now<=len){
vis[i] = 1;
dfs(len,a[i]+now,num-1);
if(flag==1) return;
vis[i] = 0; if(a[i]==len-now || len==len-now) //此剪枝一开始没想到,超时
break;
}
}
}

形参中的三个数必须要在函数体内起到一定的作用。

回答上面的疑惑,我们不再判断是有几根,而是将num==0作为递归出口,当木棒没了,说明拼接成功了。而如果一根原木棒拼接完成,就继续深搜。

这里面一个剪枝一开始我没想到,一直TLE,具体解释见我另一个题解。

题外话:这种题目,自己实践慢慢领悟吧。

三、代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std; int n,flag;
int a[];
bool vis[]; bool cmp(const int a, const int b)
{
return a>b;
}
void dfs(int len,int now,int num) //预设的原木棒的长度 正在完成的木棒的长度 剩余的小木棒数量
{
if(num==){
flag = ;
return;
}
if(now==len) dfs(len,,num);
for(int i=;i<=n;i++){
if(!vis[i] && a[i]+now<=len){
vis[i] = ;
dfs(len,a[i]+now,num-);
if(flag==) return;
vis[i] = ; if(a[i]==len-now || len==len-now) //此剪枝一开始没想到,超时
break;
}
}
}
int main()
{
while(scanf("%d",&n) && n){
int sum=;
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
sum += a[i]; //记录现在所有木棒的长度之和
}
sort(a+,a++n,cmp); //将数组a中的元素从大到小排列
int len;
flag = ;
//原木棒长度一定大于等于现在的任何一支木棒(即大于等于最长的木棒)
//原木棒长度一定小于等于现在所有木棒的长度之和
for(len=a[];len<=sum;len++){ //a[1]为最长木棒的长度
if(sum%len==){ //原木棒的根数一定是个整数
memset(vis,,sizeof(vis));
dfs(len,,n); //假设原木棒长度为len,要拼的原木棒已拼成的长度为0,还有n根木棒
if(flag==){ //已经拼成功,就退出,因为要原木棒尽可能短
break;
}
}
}
printf("%d\n",len); //打印原木棒的长度
}
return ;
}

DFS(7)——poj1011Sticks的更多相关文章

  1. DFS(深度优先)算法编程实践

    DFS定义 DFS(Depth-First-Search)深度优先搜索算法,是搜索算法的一种.是一种在开发爬虫早期使用较多的方法.它的目的是要达到被搜索结构的叶结点 . 特点 每次深度优先搜索的结果必 ...

  2. 拓扑排序+DFS(POJ1270)

    [日后练手](非解题) 拓扑排序+DFS(POJ1270) #include<stdio.h> #include<iostream> #include<cstdio> ...

  3. DFS(一):深度优先搜索的基本思想

    采用搜索算法解决问题时,需要构造一个表明状态特征和不同状态之间关系的数据结构,这种数据结构称为结点.不同的问题需要用不同的数据结构描述. 根据搜索问题所给定的条件,从一个结点出发,可以生成一个或多个新 ...

  4. 深度优先搜索DFS(一)

      实例一  0/1背包问题:   有n件物品,每件物品的重量为w[i],价值为c[i].现在需要选出若干件物品放入一个容量为V的背包中,使得在选入背包的物品重量和不超过容量V的前提下,让背包中的物品 ...

  5. 万能的搜索--之DFS(二)

    (一)深度优先搜索(DFS) 我们先给出深度优先的解决办法,所谓深度优先搜索,在迷宫问题里就是不撞南墙不回头,能走得深一点就尽量深一点.如果碰到了墙壁就返回前一个位置尝试其他的方向.在<啊哈!算 ...

  6. DFS(二):骑士游历问题

    在国际象棋的棋盘(8行×8列)上放置一个马,按照“马走日字”的规则,马要遍历棋盘,即到达棋盘上的每一格,并且每格只到达一次.例如,下图给出了骑士从坐标(1,5)出发,游历棋盘的一种可能情况. [例1] ...

  7. DFS(四):剪枝策略

    顾名思义,剪枝就是通过一些判断,剪掉搜索树上不必要的子树.在采用DFS算法搜索时,有时候我们会发现某个结点对应的子树的状态都不是我们要的结果,这时候我们没必要对这个分支进行搜索,砍掉这个子树,就是剪枝 ...

  8. DFS(三):八皇后问题

    [例1]八皇后问题. 在一个8×8国际象棋盘上,放置8个皇后,每个皇后占一格,要求皇后间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行.同一列或同一对角线上.问共有多少种不同的放置方法? (1 ...

  9. 【递归入门】组合+判断素数:dfs(递归)

    题目描述 已知 n 个整数b1,b2,…,bn,以及一个整数 k(k<n).从 n 个整数中任选 k 个整数相加,可分别得到一系列的和. 例如当 n=4,k=3,4 个整数分别为 3,7,12, ...

随机推荐

  1. ListItem Updating事件监视有没有上传附件

    using System; using System.Collections.Generic; using System.Text; using Microsoft.SharePoint; using ...

  2. 极光推送小结 - iOS

    此次即友盟分享小结(友盟分享小结 - iOS)之后对推送也进行了一版优化.此次分享内容依然基于已经成功集成 SDK 后 code 层级部分. 注:此次分享基于 SDK 3.1.0,若版本相差较大,仅供 ...

  3. Javascript的加载

    最新博客站点:欢迎来访 1. 浏览器加载     (1) 同步加载 在网页中,浏览器加载js文件的方式是通过<script>标签.如下所示: //内嵌脚本 <script type= ...

  4. 滑动窗口(poj,线段树维护区间最值)

    题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...

  5. Percona-Tookit工具包之pt-table-sync

      Preface       We've used pt-table-checksum to checksum the different table data bwtween replicatio ...

  6. jquery图片滚动normalizy.css

    article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block; ...

  7. 如何理解NaN?

    NaN这个特殊的Number与所有其他值都不相等,包括它自己:   NaN===NaN:  //false   唯一能判断NaN的方法是通过isNaN()函数:   isNaN(NaN);  //tr ...

  8. [转]JavaScript中的匿名函数及函数的闭包

    JavaScript中的匿名函数及函数的闭包  原文地址:http://www.cnblogs.com/wl0000-03/p/6050108.html 1.匿名函数 函数是JavaScript中最灵 ...

  9. python学习之字符串常用方法和格式化字符串

    Python中的字符串同样适用标准的序列操作(索引,分片,乘法,成员判断,求长度,取最小值和最大值),但因为字符串是不可变的,因此字符串不支持分片赋值. s='http://www.baidu.com ...

  10. 谭浩强C语言第四版第九章课后习题7--9题(建立,输出,删除,插入链表处理)

    #include<stdio.h> #include<stdlib.h> #define N sizeof(link) typedef struct stu { struct ...