小木棍 [数据加强版]
Posted ppxppx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小木棍 [数据加强版]相关的知识,希望对你有一定的参考价值。
洛咕
双倍经验---多组数据
题意:乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50.现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度.给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度.
分析:首先读入的时候把长度大于50的自动过滤掉,剩下n根长度小于等于50的木棍,设这n根小木棍的长度和为\(tot\),长度最大的为\(val\).
我们直接从小到大枚举原始木棍的长度,并通过dfs判断是否合法即可.枚举的下界是一个小木棍的最大长度\(val\),上界是长度和\(tot\).设当前枚举的原始木棍的长度为\(len\),那么\(tot\)必然要能被\(len\)整除,否则不合法,若能够被整除,显然我们要是能够拼凑出\(sum=tot/len\)根长度为\(len\)的木棍就是合法答案.
接下来就只要考虑dfs的剪枝操作了.
一,我们把木棍长度从大到小排序,优先考虑较长的木棍,显然能减少状态数.
二,既然剪枝一已经把木棍排序了,那么我们干脆固定每次填入的木棍长度是递减的.这个只要dfs的变量增加一个last,表示当前从第last根木棍开始考虑就好了.
三,假设我们给一根"空"的 填入木棍,也就是当前的木棍长度\(cnt=0\),那么当填入\(a[i]\)后该搜索状态不合法,那么直接判定当前分支不合法,因为你把\(a[i]\)填入剩下的其它的"空"的,都会是不合法的.
四,跟三类似,如果我们当前填完了\(a[i]\)之后,填完了一个长度为len的木棍,发现该搜索状态不合法,那么直接判定当前分支不合法,因为你再用别的若干根短的木棍来代替\(a[i]\),那么接下来搜索下一根木棍还会是不合法的.
五,如果填入\(a[i]\)不合法,如果\(a[i+1]=a[i]\)那么直接不要考虑填.
这些剪枝真的是缺一不可.亲测~~~
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read()
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
const int N=105;
int n,tot,val,sum,len;
int a[N],visit[N];
//当前正在拼第now跟木棒
//第now跟木棒已经拼出了长度cnt
//当前已经考虑到了第last根木棍
inline bool dfs(int now,int cnt,int last)
if(now>sum)return true;//sum根木棒都拼完了
if(cnt==len)return dfs(now+1,0,1);//当前这根拼完了
int fail=0;//剪枝五用的
for(int i=last;i<=n;++i)
if(!visit[i]&&cnt+a[i]<=len&&fail!=a[i])
visit[i]=1;
if(dfs(now,cnt+a[i],i+1))return true;
fail=a[i];//记录不要填与a[i]相同长度的木棍了
visit[i]=0;//回溯
if(!cnt||cnt+a[i]==len)return false;//剪枝三,四
return false;
int main()
int nn=read();
for(int i=1;i<=nn;++i)
int b=read();
if(b<=50)//过滤不合法的木棍
a[++n]=b;tot+=b;//记录长度和
val=max(b,val);//比较最长木棍
sort(a+1,a+n+1);reverse(a+1,a+n+1);//从大到小排序
for(len=val;len<=tot;++len)//枚举原始木棍长度为len
if(tot%len)continue;//不能整除肯定不合法
sum=tot/len;//要拼凑出sum根木棍
memset(visit,0,sizeof(visit));//初始化
if(dfs(1,0,1))
printf("%d\n",len);
break;
return 0;
以上是关于小木棍 [数据加强版]的主要内容,如果未能解决你的问题,请参考以下文章