洛谷P1120:https://www.luogu.org/problemnew/show/P1120

思路

明显是搜索题嘛

但是这数据增强不是一星半点呐

我们需要N多的剪枝

PS:需要先删去超出50的木棍

首先我们可以想到枚举每个小木棍的长度来搜索

但是直接枚举肯定会超时的 所以我们想到优化剪枝

因为要组成木棍肯定要从被砍开的木棍中的最大值开始枚举到所有木棍总和长(只有一根木棍被砍开)

然而这样却还不是最优的剪枝 因为每根原始小木棍的长度一样 所以枚举长度的时候可以判断是否被总和整除

而且我们只需要枚举到总和的一半即可 因为如果分成两根或以下行不通的话 到最后只需要输出总长就行(只有一根木棍)

因为短的可以组合得比长的更灵活 因此我们可以把木棍从大到小排序之后再选择

进入DFS后我们需要判断如果当前枚举的这根木棍还需要凑的长度为0 且已经满足:凑出的根数已经足够 (凑出长棍的根数=所有木棍的长度之和/原始长度)

当DFS失败时 我们需要退出并换另外一根长度不同的木棍 因为一样长度的可能有很多 所以时间浪费了 我们需要在进入DFS之前预处理出所有木棍下一根不同长度的编号

可以根据木棍长度的单调性来二分找出第一个木棍长度不大于未拼长度rest

参考洛谷某dalao的难想却特别特别重要剪枝:

如果当前长棍剩余的未拼长度等于当前木棍的长度或原始长度,继续拼下去时却失败了,就直接回溯并改之前拼的木棍

解释:

当前长棍剩余的未拼长度等于当前木棍的长度时,当前木棍明显只能自组一根长棍,但继续拼下去却失败,说明这根木棍不能自组?!这根木棍不自组就没法用上了,所以不用搜更短的木棍了,直接回溯,改之前的木棍;

 当前长棍剩余的未拼长度等于原始长度时,说明这根原来的长棍还一点没拼,现在正在放入一根木棍。很明显,这根木棍还没有跟其它棍子拼接,如果现在拼下去能成功话,它肯定是能用上的,即自组或与其它还没用的木棍拼接。但继续拼下去却失败,说明现在这根木棍不能用上,无法完成拼接,所以直接回溯,改之前的木棍。

代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 70
int n,k,minn,sum,c,num,len;
int mood[maxn],nex[maxn];//nex是预处理编号
bool vis[maxn],flag;
int cinn()
{
int x=,f=;
char ch=;
while(!isdigit(ch))
f|=(ch=='-'),ch=getchar();
while(isdigit(ch))
x=(x<<)+(x<<)+(ch^),ch=getchar();
return f?-x:x;
}
void write(int x)
{
if(x<)putchar('-'),x=-x;
if(x>=)write(x/);
putchar(x%+'');
}
bool cmp(int a,int b)
{
return a>b;
}
void dfs(int p,int last,int rest)//p是当前已经拼倒第几根 last是上一根用的编号 rest是还要多长
{
int i;
if(!rest)//还需要0长度的木棍
{
if(p==num)//如果已经凑齐了所有木棍
{
flag=;
return;
}
for(i=;i<=n;i++)//如果还没凑齐 找一根还没用过的当第一根要用的
if(!vis[i]) break;
vis[i]=;
dfs(p+,i,len-mood[i]);//搜索下一根
vis[i]=;
if(flag) return;
}
int l=last+,r=n,mid;
while(l<r)//二分找编号
{
mid=(l+r)>>;
if(mood[mid]<=rest) r=mid;
else l=mid+;
}
for(i=l;i<=n;i++)//注意从第一根不同的编号开始而不是从1开始
{
if(!vis[i])
{
vis[i]=;
dfs(p,i,rest-mood[i]);
vis[i]=;
if(flag) return;
if(rest==mood[i]||rest==len) return;//最后一个剪枝
i=nex[i];//更换小木棍
if(i==n) return;
}
}
}
void read()
{
n=cinn();
while(n)
{
int x;
x=cinn();
if(x<=)//删去大于50的木棍
{
sum+=x;
mood[++k]=x;
}
n--;
}
n=k;
sort(+mood,+mood+n,cmp);//从大到小排序
minn=mood[];//木棍中的最大值是枚举长度的最小值
nex[n]=n;
for(int i=n-;i>;i--)//预处理编号
{
if(mood[i]==mood[i+]) nex[i]=nex[i+];
else nex[i]=i;
}
}
int main()
{
read();
for(len=minn;len<=sum/;len++)
{
if(sum%len==)//整除
{
num=sum/len;//小木棍根数
flag=;
vis[]=;
dfs(,,len-minn);//取了第一根
vis[]=;
if(flag)
{
write(len);//如果满足输出
return ;
}
}
}
write(sum);//只有一根木棍
}

【题解】洛谷P1120 小木棍(搜索+剪枝+卡常)的更多相关文章

  1. 洛谷P1120 小木棍 [搜索]

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

  2. 洛谷 P1120 小木棍 dfs+剪枝

    Problem Description [题目链接] https://www.luogu.com.cn/problem/P1120 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不 ...

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

    洛谷P1120 小木棍 [数据加强版] 搜索+剪枝 [剪枝操作]:若某组拼接不成立,且此时 已拼接的长度为0 或 当前已拼接的长度与刚才枚举的长度之和为最终枚举的答案时,则可直接跳出循环.因为此时继续 ...

  4. 洛谷P1120 小木棍

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

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

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

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

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

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

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

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

    题目传送 一道特别毒瘤能提醒人不要忘记剪枝的题. 首先不要忘了管理员的话.忘把长度大于50的木棍过滤掉真的坑了不少人(包括我). 显然是一道DFS题 .考虑剪枝. 找找搜索要面临的维度.状态:原始木棍 ...

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

    这道题可能是我做过的数据最不水的一道题-- 题目传送门 这题可以说是神剪枝,本身搜索并不算难,但剪枝是真不好想(好吧,我承认我看了题解)-- 剪枝: 用桶来存储木棍 在输入的时候记录下最长的木棍和最短 ...

随机推荐

  1. swagger2配置和使用

    1.导入swagger2 <dependency> <groupId>io.springfox</groupId> <artifactId>spring ...

  2. 基于easyUI实现系统日志管理

    此文章是基于 EasyUI+Knockout实现经典表单的查看.编辑 一. 相关文件介绍 1. log.jsp:系统日志管理界面 <!DOCTYPE html PUBLIC "-//W ...

  3. freemarker生成word,表格分页

    在做项目的过程中,使用到了freemarker生成word.又有一个需求,明细的要确定有多少页,这就用到了换页的xml标签了,找了我好久 <w:p ><w:r><w:br ...

  4. ccf-201712-2 游戏

    问题描述 有n个小朋友围成一圈玩游戏,小朋友从1至n编号,2号小朋友坐在1号小朋友的顺时针方向,3号小朋友坐在2号小朋友的顺时针方向,--,1号小朋友坐在n号小朋友的顺时针方向. 游戏开始,从1号小朋 ...

  5. Ant design 项目打包后报错:"Menu(or Flex) is not defined"

    我的项目使用了ant-design 和 ant-design-mobile,在测试环境上没问题,但是打包发布之后控制台报错 Menu is not defined Flex is not define ...

  6. vue-cli脚手架项目实例

    看完了配置,接下来通过一个实例,更清晰地了解这些文件之间的联系,顺带练习练习vue相关知识. 1.安装 打开命令行控制器,系统自带cmd或者git bash等都可以,按照顺序输入如下指令,耐心等待每一 ...

  7. 微信小程序request请求之GET跟POST的区别

    1.GET 例子: wx.request({ url: 'test.php', //仅为示例,并非真实的接口地址 data: { x: '' , y: '' }, header: { 'content ...

  8. iview框架下,modal内容过长,select选项位置不对

    问题 modal组件中内容过长,超过一屏,有滚动条后,里面包含的select组件选项内容,位置会不对 解决 在使用select的时候添加transfer属性

  9. <Android 基础(十九)> CoordinatorLayout

    介绍 CoordinatorLayout,中文翻译,协调布局,顾名思义,此布局中的子View之间,子View与父布局之间应该是可以协调工作的,如何协调,Behavior. 今天看下Android St ...

  10. arcgis server10.1 gp GetResultMapServiceLayer

    根据10.1文档 silverlight 里面提供了新的_geoprocessorTask.GetResultMapServiceLayer方法 研究了一下得知 原来的GetResultImageLa ...