题目链接

http://poj.org/problem?id=1011

题意

输入n根棍子的长度,将这n根棍子组合成若干根长度相同的棍子,求组合后的棍子的最小长度。这题是poj2362的加强版,思路与poj2362相同,只是在2362的基础上添加了剪枝操作,做这题之前先去做poj2362效果最好。

思路

由于棍子越长,组合时的灵活性越差,所以要先从长棍子开始搜索,则首先要将n根棍子从长到短排序,然后从最长的棍子开始dfs。由于棍子最多可以有64根,不剪枝的话肯定会超时。以下是几种剪枝方法:

(1)假设n根棍子中最长的长度为maxLen,n根棍子的长度和为sum,最后求得的结果为len,则len∈[maxLen,sum],且sum%len==0;

(2)由于所有的棍子都降序排序,在组合的过程中若某一棍子不合适,则跳过该棍子后面与其长度相同的所有棍子;

(3)最重要的剪枝:在组合新棍子时,如果添加的第一根棍子stick[i]和剩余的所有棍子都无法组合,则不用继续往下搜索,直接返回(如果继续搜索,到最后stick[i]会被剩下)。

代码

未剪枝代码(超时,dfs部分与poj2362的代码基本相同):

 #include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std; const int INF = <<;
const int N = ;
vector<int> stick;
int visit[N];
int n;
int ans; bool cmp(int a, int b)
{
return a > b; //棍子从长到短排序
} /*
* cur : 当前从第cur根棍子开始尝试组合
* nums : 当前还有nums根新棍子未组合完成
* curLen :当前组合的棍子长度
* len : 要组合的新棍子长度
*/
bool dfs(int cur, int nums, int curLen, int len)
{
if(nums==)
return true; for(int i=cur; i<n; i++)
{
if(visit[i])
continue;
visit[i] = ;
if(curLen+stick[i]<len)
{
if(dfs(cur+, nums, curLen+stick[i], len))
return true;
}
else if(curLen+stick[i]==len)
{
if(dfs(, nums-, , len))
return true;
}
visit[i] = ;
}
return false;
} int main()
{
//freopen("poj1011.txt", "r", stdin);
while(cin>>n && n)
{
int sum = ;
stick.clear();
for(int i=; i<n; i++)
{
int len;
cin>>len;
sum += len;
stick.push_back(len);
} ans = INF;
sort(stick.begin(), stick.end(), cmp);
for(int i=stick[]; i<=sum; i++)
{
if(sum % i != )
continue;
memset(visit, , sizeof(visit));
if(dfs(, sum/i, , i))
{
cout<<i<<endl;
break;
}
}
}
return ;
}

剪枝后代码(AC):

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std; const int INF = <<;
const int N = ;
vector<int> stick;
int visit[N];
int n;
int ans; bool cmp(int a, int b)
{
return a > b; //棍子从长到短排序
} /*
* cur : 当前从第cur根棍子开始尝试组合
* nums : 当前还有nums根新棍子未组合完成
* curLen :当前组合的棍子长度
* len : 要组合的新棍子长度
*/
bool dfs(int cur, int nums, int curLen, int len)
{
if(nums==)
return true; int same = -; //剪枝(2)
for(int i=cur; i<n; i++)
{
if(visit[i] || stick[i]==same)
continue;
visit[i] = ;
if(curLen+stick[i]<len)
{
if(dfs(cur+, nums, curLen+stick[i], len))
return true;
else same = stick[i];
}
else if(curLen+stick[i]==len)
{
if(dfs(, nums-, , len))
return true;
else same = stick[i];
}
visit[i] = ;
if(curLen==) //剪枝(3)
break;
}
return false;
} int main()
{
//freopen("poj1011.txt", "r", stdin);
while(cin>>n && n)
{
int sum = ;
stick.clear();
for(int i=; i<n; i++)
{
int len;
cin>>len;
sum += len;
stick.push_back(len);
} ans = INF;
sort(stick.begin(), stick.end(), cmp);
for(int i=stick[]; i<=sum; i++)
{
if(sum % i != ) //剪枝(1)
continue;
memset(visit, , sizeof(visit));
if(dfs(, sum/i, , i))
{
cout<<i<<endl;
break;
}
}
}
return ;
}

poj1011 Sticks(DFS+剪枝)的更多相关文章

  1. poj1011 Sticks(dfs+剪枝)

    Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 110416   Accepted: 25331 Descrip ...

  2. poj1011(DFS+剪枝)

    题目链接:https://vjudge.net/problem/POJ-1011 题意:给定n(<=64)条木棍的长度(<=50),将这些木棍刚好拼成长度一样的若干条木棍,求拼出的可能的最 ...

  3. poj 1011 :Sticks (dfs+剪枝)

    题意:给出n根小棒的长度stick[i],已知这n根小棒原本由若干根长度相同的长木棒(原棒)分解而来.求出原棒的最小可能长度. 思路:dfs+剪枝.蛮经典的题目,重点在于dfs剪枝的设计.先说先具体的 ...

  4. POJ1011 (DFS+剪枝)

    Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 129606   Accepted: 30388 Descrip ...

  5. POJ 1011 - Sticks DFS+剪枝

    POJ 1011 - Sticks 题意:    一把等长的木段被随机砍成 n 条小木条    已知他们各自的长度,问原来这些木段可能的最小长度是多少 分析:    1. 该长度必能被总长整除    ...

  6. poj1011 && uva307 DFS + 剪枝

    将木棒从大到小排列,保证每次的选择都是最长可选的木棒. 剪枝: 1 . 如果第 i 根木棒被选择却无法成功拼接,那么后面与其长度相同的也不能选择. 2 . 如果第 cnt + 1 根木棒无法成功拼接, ...

  7. hdu 1145(Sticks) DFS剪枝

    Sticks Problem Description George took sticks of the same length and cut them randomly until all par ...

  8. POJ 1011 Sticks dfs,剪枝 难度:2

    http://poj.org/problem?id=1011 要把所给的集合分成几个集合,每个集合相加之和ans相等,且ans最小,因为这个和ans只在[1,64*50]内,所以可以用dfs一试 首先 ...

  9. DFS(剪枝) POJ 1011 Sticks

    题目传送门 /* 题意:若干小木棍,是由多条相同长度的长木棍分割而成,问最小的原来长木棍的长度: DFS剪枝:剪枝搜索的好题!TLE好几次,终于剪枝完全! 剪枝主要在4和5:4 相同长度的木棍不再搜索 ...

  10. poj 1011 Sticks (DFS+剪枝)

    Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 127771   Accepted: 29926 Descrip ...

随机推荐

  1. mysqldump 和 sql命令导入sql文件

    注意:不是进入mysql命令行操作的::: mysqldump -uroot -p --database x3gbk >x3gbk.sql 回车会出发,输入密码; 直接在-p后输入密码,有时候这 ...

  2. maven创建spring项目之后,启动报错java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener

    出错情景:maven中已经加载了spring的核心包,但是项目启动时,报错: org.apache.catalina.core.StandardContext listenerStart严重: Err ...

  3. HTML5增强的表单

    form元素a.用来定义一个表单,是建立表单的基础元素(就类似定义表格的table)b.表单的其他元素包含在form元素中,其主要子元素有:input/button/select......form元 ...

  4. Nodejs文件监控chokidar

    最近有个需求是扫描用例,用例是放在svn上,如果每次扫描都去遍历目录的话会有占用太多的io,所以想着用文件监控,有文件变化时只对该文件进行操作. Nodejs里的 chokidar 模块可以更好的对文 ...

  5. 开发技巧:高效的使用 Response.Redirect

    我正在评估一个 ASP.NET Web 项目应用.它有一些可扩展性问题.意味着当网站访问量增加的时候.系统将会变得缓慢.当我查看应用日志.我找到了大量的 ThreadAbortException. 这 ...

  6. 一般处理程序、ASP.NET核心知识(5)

    初窥 1.新建一个一般处理程序 新建一个一般处理程序 2.看看里头的代码 public class MyHandler : IHttpHandler { public void ProcessRequ ...

  7. HDU 5995 Kblack loves flag (模拟)

    题目链接 Problem Description Kblack loves flags, so he has infinite flags in his pocket. One day, Kblack ...

  8. HDU 1034 Candy Sharing Game (模拟)

    题目链接 Problem Description A number of students sit in a circle facing their teacher in the center. Ea ...

  9. 蓝色简单的cms文档管理系统模板——后台

    链接:http://pan.baidu.com/s/1qYMwHis 密码:xyiw

  10. 自定义 feign 反序列化时间字符格式

    参考 : https://blog.csdn.net/forezp/article/details/73480304 feign client 默认配置类:默认的配置类为FeignClientsCon ...