poj1011 Sticks(DFS+剪枝)
题目链接
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+剪枝)的更多相关文章
- poj1011 Sticks(dfs+剪枝)
Sticks Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 110416 Accepted: 25331 Descrip ...
- poj1011(DFS+剪枝)
题目链接:https://vjudge.net/problem/POJ-1011 题意:给定n(<=64)条木棍的长度(<=50),将这些木棍刚好拼成长度一样的若干条木棍,求拼出的可能的最 ...
- poj 1011 :Sticks (dfs+剪枝)
题意:给出n根小棒的长度stick[i],已知这n根小棒原本由若干根长度相同的长木棒(原棒)分解而来.求出原棒的最小可能长度. 思路:dfs+剪枝.蛮经典的题目,重点在于dfs剪枝的设计.先说先具体的 ...
- POJ1011 (DFS+剪枝)
Sticks Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 129606 Accepted: 30388 Descrip ...
- POJ 1011 - Sticks DFS+剪枝
POJ 1011 - Sticks 题意: 一把等长的木段被随机砍成 n 条小木条 已知他们各自的长度,问原来这些木段可能的最小长度是多少 分析: 1. 该长度必能被总长整除 ...
- poj1011 && uva307 DFS + 剪枝
将木棒从大到小排列,保证每次的选择都是最长可选的木棒. 剪枝: 1 . 如果第 i 根木棒被选择却无法成功拼接,那么后面与其长度相同的也不能选择. 2 . 如果第 cnt + 1 根木棒无法成功拼接, ...
- hdu 1145(Sticks) DFS剪枝
Sticks Problem Description George took sticks of the same length and cut them randomly until all par ...
- POJ 1011 Sticks dfs,剪枝 难度:2
http://poj.org/problem?id=1011 要把所给的集合分成几个集合,每个集合相加之和ans相等,且ans最小,因为这个和ans只在[1,64*50]内,所以可以用dfs一试 首先 ...
- DFS(剪枝) POJ 1011 Sticks
题目传送门 /* 题意:若干小木棍,是由多条相同长度的长木棍分割而成,问最小的原来长木棍的长度: DFS剪枝:剪枝搜索的好题!TLE好几次,终于剪枝完全! 剪枝主要在4和5:4 相同长度的木棍不再搜索 ...
- poj 1011 Sticks (DFS+剪枝)
Sticks Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 127771 Accepted: 29926 Descrip ...
随机推荐
- 不管谁坐了CIO的位置 都必须了解的法则
目前一些设立了CIO岗位的央企中,CIO也只做到了“IO”(信息官,Information Officer),而没有做到“C”(首席,Chief).老总们总在抱怨没有合适的人选:懂技术的不懂业务,懂业 ...
- 「LibreOJ β Round #4」多项式 (广义欧拉数论定理)
https://loj.ac/problem/525 题目描述 给定一个正整数 kkk,你需要寻找一个系数均为 0 到 k−1之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x)modk= ...
- NOIP2013 提高组 Day2
期望得分:100+100+30+=230+ 实际得分:100+70+30=200 T2 觉得题目描述有歧义: 若存在2i却不存在2i+1,自己按不合法做的,实际是合法的 T3 bfs 难以估分 虽然 ...
- Codeforces 807 C. Success Rate
http://codeforces.com/problemset/problem/807/C C. Success Rate time limit per test 2 seconds memory ...
- Date、String、Calendar相互转化
Date是在Jdk1.0出现的专门用来处理时间的类,但是由于Date在国际化方面存在限制,在Jdk1.1推出Calendar,现在Date的很多方法都已经过时,都迁移到Calendar上. 1.Dat ...
- 20155117王震宇 实验一《Java开发环境的熟悉》实验报告
(一)使用JDK编译.运行简单的java程序 命令创建实验目录 输入mkdir 2051117 创建以自己学号命名的文件夹,通过cd命令移动到指定文件夹,输入mkdir exp1创建实验文件夹. 打开 ...
- session_write_close()的作用
简单地说,当开启session_start以后,这个session会一直开启,并且被一个用户使用.其他用户开启session的话要等待第一个session用户关闭以后才可以开启sessio,这样就造成 ...
- php跳转网络连接
laravel用 redirect 跳转 HTTP 即可.可以把网址看作路由 例如: if($newsInfo->type == 77){ return redirect('http://192 ...
- IntelliJ Idea key shortcuts
>Default explaination Official IntelliJ Idea 常用快捷键列表 Shortcuts Ctrl+Shift + Enter,语句完成 "!&qu ...
- flask插件系列之flask_celery异步任务神器
现在继续学习在集成的框架中如何使用celery. 在Flask中使用celery 在Flask中集成celery需要做到两点: 创建celery的实例对象的名字必须是flask应用程序app的名字,否 ...