一本通&&洛谷——P1120 小木棍 [数据加强版]——题解


一道特别毒瘤能提醒人不要忘记剪枝的题。
首先不要忘了管理员的话。忘把长度大于50的木棍过滤掉真的坑了不少人(包括我)。
显然是一道DFS题 。考虑剪枝。
找找搜索要面临的维度、状态:原始木棍的长度len,原始木棍的条数m,当前正在拼第k条原始木棍、还剩下没拼完的长度rest,木根的编号。
去等效冗杂考虑:
1、为了祛除冗杂,我们可以假设拼成一根原始木棍的若干小木棍的长度x1,x2,x3,x4,x5...满足x1<x2<x3<x4<x5<...同时把小木棍的长度从大到小排个序,每次找符合条件的小木棍时都从上一个符合条件的小木棍的后面去找,这样就不会有拼成小木棍长度的序列的元素相同,只因为顺序不同就重复搜索的情况了。
2、注意可能有长度相同的小木棍,当我们试完一个小木棍后,再试长度跟它相同的小木棍时,显然得到的情况是一样的,所以应该试下一个长度不同的小木棍,即跳过长度与它相同的小木棍(这里我用预处理处理出每个小木棍的长度与它相等的最后一根小木棍的编号)。
可行性剪枝考虑:
1、一个非常暴力的思路是从0开始到所有木根长度的总和sum枚举len搜索。显然超时妥妥的,所以考虑优化。发现m一定是个整数,所以len一定是sum的因数。而len只需枚举到sum/2就可以了。因为如果len枚举到sum/2后都没找到答案,那答案只能是所有小木棍拼成一个大木棍的长度。
2、当k==m时,剩下的小木棍的长度总和等于len,即一定能拼成一条原始木棍,所以直接回溯即可。
3、当resti(当前找到的小木棍为i时的rest)正好等于找到的符合条件的小木棍i的长度、并把它拼上,之后却不能把所有原始木棍拼出,那么resti在接下来拼木棍时肯定不能得到答案,所以直接回溯。因为resti拼完时,要么使用小木棍i,要么用几根长度和等于小木棍i的长度的小木棍才能刚好把resti拼完。本来那几根小木棍就不能与剩下的小木棍拼出还要拼的原始木棍,当那几根小木棍换成总长度一样,但个数为1的小木棍i后,不就更不能拼出还要拼的原始木棍了吗?
最优性剪枝考虑:找到答案后立即回溯,其他的操作都不管。
实现优化:
1、当我们在找接下来要用哪条木棍拼时可以用二分查找在第last(一条符合条件的小木棍的编号)+1条到最后一条木棍中第一条长度小于等于rest的木棍。
2、我们在每次回溯时把used数组恢复,而避免用memset(memset用多了,慢到崩溃)
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype> using namespace std; bool used[],bj; int a[],n,sum,m,len,nxt[],ans; char ch; bool cmp(int a,int b)
{
return a>b;
} inline int read()//吓得都用快读了
{
ans=;
ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) ans=(ans<<)+(ans<<)+ch-'',ch=getchar();
return ans;
} void dps(const int &k,const int &last,const int &rest)
{
if(k==m) {bj=;return;}//可行性剪枝2
if(!rest)
{
for(int i=;i<=n;i++)
if(!used[i])
{
used[i]=;
dps(k+,i,len-a[i]);
used[i]=;//别忘了回溯,因为可能影响到搜索树的“舅舅节点”。
return;
}
}
int l=last+,r=n,mid;
while(l<r)//
{
mid=(l+r)>>;
if(a[mid]<=rest) r=mid;
else l=mid+;
}
for(int i=l;i<=n;i++)
if(!used[i])
{
used[i]=;
dps(k,i,rest-a[i]);//可行性剪枝3
if(bj) return;//最优性剪枝
used[i]=;
if(rest==a[i]) return;
i=nxt[i];
}
} int main()
{
n=read();
int tot=;
int b;
for(int i=;i<=n;i++)
{
b=read();
if(b<=)
{
a[++tot]=b;
sum+=b;
}
}
n=tot;
sort(a+,a+n+,cmp);
for(int i=n;i>=;i--)//预处理
{
if(a[i]==a[i+]) nxt[i]=nxt[i+];
else nxt[i]=i;
}
int s=sum/;used[]=;
for(len=a[];len<=s;len++)
if(sum%len==)//可行性剪枝1
{
bj=;
m=sum/len;
dps(,,len-a[]);
if(bj)
{
printf("%d",len);
return ;
}
}
if(!bj) cout<<sum;
return ;
}
一本通&&洛谷——P1120 小木棍 [数据加强版]——题解的更多相关文章
- 洛谷 P1120 小木棍 [数据加强版]解题报告
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
- 洛谷——P1120 小木棍 [数据加强版]
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍 ...
- 洛谷 P1120 小木棍 [数据加强版]
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
- 洛谷—— P1120 小木棍 [数据加强版]
https://www.luogu.org/problem/show?pid=1120 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接 ...
- [洛谷P1120]小木棍 [数据加强版]
题目大意:有一些同样长的木棍,被切割成几段(长$\leqslant$50).给出每段小木棍的长度,找出原始木棍的最小可能长度. 题解:dfs C++ Code: #include<cstdio& ...
- 洛谷P1120 小木棍 [数据加强版]搜索
玄学剪支,正好复习一下搜索 感觉搜索题的套路就是先把整体框架打出来,然后再一步一步优化剪枝 1.从maxv到sumv/2枚举长度(想一想,为什么) 2. 开一个桶,从大到小开始枚举 3. 在搜索中,枚 ...
- P1120 小木棍 [数据加强版] 回溯法 终极剪枝
题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度 ...
- P1120 小木棍 [数据加强版]
题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编 ...
- P1120 小木棍 [数据加强版](poj 1011)
题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编 ...
随机推荐
- 初学node.js-nodejs中实现用户注册路由
经过前面几次的学习,已经可以做下小功能,今天要实现的事用户注册路由. 一.users_model.js 功能:定义用户对象模型 var mongoose=require('mongoose'), S ...
- SQL server字符分割
USE [vanke_develop] GO /****** Object: UserDefinedFunction [dbo].[func_Split] Script Date: 2019/5/22 ...
- linux 进程1
一. 进程的开始和结束 1.1. main函数的调用 a. 编译链接时的引导代码.操作系统下的应用程序其实在main执行前也需要先执行一段引导代码才能去执行main,我们写应用程序时不用考虑引导代码的 ...
- 卷积神经网络(ConvNets)中卷积的实现
#include <iostream> #include <sstream> #include <fstream> #include <algorithm&g ...
- 【SSL2325】最小转弯问题
题面: \[\Large\text{最小转弯问题}\] \[Time~Limit:1000MS~~Memory~Limit:65536K\] Description 给出一张地图,这张地图被分为 n× ...
- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'p.knowlege_part_id' in 'field list'
MyBatis中,出现Unknown column的提示是mapper.xml中的数据库字段写错了. 错误示例: XxMapper.xml中 <sql id="KnowlegeSect ...
- tensorflow学习笔记一----------tensorflow安装
2016年11月30日,tensorflow(https://www.tensorflow.org/)更新了0.12版本,这标志着我们终于可以在windows下使用tensorflow了(但是还是推荐 ...
- css重置的各种版本总结
个人手机端常用到的: @charset "utf-8"; body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ...
- 卸载OpenIV
最近把 GTA5 卸载了,于是也想把用来修改 MOD 的 OpenIV 也卸载了. 结果在设置中,进行卸载的时候,弹出这个窗口 解决方案 1.首先打开 文件所在位置 2.右键,选择 属性,打开文件所在 ...
- php手动实现ip2long和long2ip
php手动实现ip2long和long2ip /** * 测试 */ public function testipAction() { $ip = '10.58.101.175'; echo ip2l ...