题目传送

一道特别毒瘤能提醒人不要忘记剪枝的题。

首先不要忘了管理员的话。忘把长度大于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 小木棍 [数据加强版]——题解的更多相关文章

  1. 洛谷 P1120 小木棍 [数据加强版]解题报告

    P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...

  2. 洛谷——P1120 小木棍 [数据加强版]

    P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍 ...

  3. 洛谷 P1120 小木棍 [数据加强版]

    P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...

  4. 洛谷—— P1120 小木棍 [数据加强版]

    https://www.luogu.org/problem/show?pid=1120 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接 ...

  5. [洛谷P1120]小木棍 [数据加强版]

    题目大意:有一些同样长的木棍,被切割成几段(长$\leqslant$50).给出每段小木棍的长度,找出原始木棍的最小可能长度. 题解:dfs C++ Code: #include<cstdio& ...

  6. 洛谷P1120 小木棍 [数据加强版]搜索

    玄学剪支,正好复习一下搜索 感觉搜索题的套路就是先把整体框架打出来,然后再一步一步优化剪枝 1.从maxv到sumv/2枚举长度(想一想,为什么) 2. 开一个桶,从大到小开始枚举 3. 在搜索中,枚 ...

  7. P1120 小木棍 [数据加强版] 回溯法 终极剪枝

    题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度 ...

  8. P1120 小木棍 [数据加强版]

    题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编 ...

  9. P1120 小木棍 [数据加强版](poj 1011)

    题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编 ...

随机推荐

  1. CNN文本分类

    CNN用于文本分类本就是一个不完美的解决方案,因为CNN要求输入都是一定长度的,而对于文本分类问题,文本序列是不定长的,RNN可以完美解决序列不定长问题, 因为RNN不要求输入是一定长度的.那么对于C ...

  2. Python解释器判断整数相加溢出

    溢出,则和的最高位(即符号位)与两个加数都不相同,例如 1)非负数+非负数=负数 2)负数+负数=非负数 那么,假设x为a与b的和,((a^b)>=0 && (x^a)<0 ...

  3. SpringBoot项目快速启动停止脚本

    SpringBoot项目快速启动停止脚本 1.在jar包同级目录下,创建 app.sh #!/bin/bash appName=`ls|grep .jar$` if [ -z $appName ] t ...

  4. [DS+Algo] 002 一维表结构

    目录 1. 顺序表 1.1 分类 1.2 实现方式 1.3 扩容问题 1.4 操作 2. 链表 2.1 分类 2.2 链表相关操作 2.3 链表 VS 顺序表 3. 关于代码实现 1. 顺序表 1.1 ...

  5. Java——HashMap使用Demo

    package map; import java.util.Collection; import java.util.HashMap; import java.util.Set; public cla ...

  6. vue element 导出 分页数据的excel表格

    1.安装相关依赖 npm install --save xlsx file-saver 2.导入相关插件 在组建头部导入相关插件 const FileSaver = require("fil ...

  7. vue router应用及总结

    编写一个小的demo,对router基础的应用学习和理解. 效果图示: 说明: 点击About在右边显示相关信息. 说明: 点击Home,在下边显示相关信息,且Home下有两个路由链接,分别对应各自的 ...

  8. 【五一qbxt】day3 动态规划

    动态规划 引例: 斐波那契数列: 边界条件:f0=0: f1=1: 能够直接被求出值的状态 不需要计算其他斐波那契数列的值直接可以得到结果: 转移方程:fn=fn-1+fn-2如何用已有状态求出未知状 ...

  9. Django @csrf_exempt不能在类视图中工作(Django @csrf_exempt not working in class View)

    我在Django 1.9中有一个使用SessionMiddleware的应用程序.我想在同一个项目中为这个应用程序创建一个API,但是在做一个POST请求时,它不能使用@csrf_exempt注释. ...

  10. CSS 属性小记

    1. 选择器的介绍 普通选择器 标签选择器:p{...} id选择器:#xiaoming{...} 类选择器:.class{...} 通用选择器: *{...}, 对所有的元素都有效 伪类选择器 Lo ...