凑木棍啦
看了下面这个恍然大悟(不知是哪位神犇)
#include<cstdio>
int n,q[110],ans=0,tot,maxx,minn;
bool tf=false;
//搜索(深搜)
void dfs(int d,int x,int t,int p)
//d是还需要拼接的木棍,x是当前拼接的长度,t是每根拼好的木棍要求的长度,p是最大能拼多长的木棍
{
if(tf)return;
//有答案就退出循环
if(d==0)
//全部木棍拼完了,找到答案
{
tot=t;
//记录答案
tf=true;
//标记有答案
return;
}
if(x==t)
//拼出了合法木棍
{
dfs(d-1,0,t,maxx);
//减少还需要拼接的个数,当前已经拼完了一根合法木棍,下一次从头拼接,最大可拼接的木棍还是可以拼所有合法木棍最大的长度
return;
}
for(int i=p;i>=minn;i--)
// 从最大可以拼接的长度开始(先取大的)
{
if(q[i]>0 && x+i<=t)
// i长度的木棍还有,且拼接后没有超出目标
{
q[i]--;
//木棍数量--
dfs(d,x+i,t,i);
//进入下一层
if(tf)return;
//有答案就退出循环
q[i]++;
//木棍数量++
if(x==0)return;
//优化:如果从dfs出来且没有答案,就是说剩下的木棍无法组成足够的合法木棍,就不用继续往下搜索了
if(x+i==t)return;
//优化:(和上一个优化有关)上一个优化跳出了 之后就会直接到这个优化(因为如果还能拼成合法木棍, 即使有x长度的木棍和y长度的木棍,x+y=i,那么也不会有更优,而且也不会拼出足够的目标木棍,就没有继续搜索的必要)
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int zz;scanf("%d",&zz);
if(zz<=50)
//坑人的点
{
q[zz]++;ans+=zz;
//记录合法木棍的总和
maxx=maxx>zz?maxx:zz;
//记录最大值
minn=minn<zz?minn:zz;
//记录最小值
}
}
for(int i=maxx;i<=ans/2;i++)
//从最小可以拼接的长度枚举(木棍中最长的), ans/2是因为枚举的i要是总 和的因子,但超过ans的一半后就不会是ans的因子了
if(!tf && ans%i==0)
//当还没有找到答案且i是ans的因子时,就搜索一次
dfs(ans/i,0,i,maxx);
if(!tf)tot=ans;
//如果没有找到答案,那就是全部拼成一根木棍
printf("%d",tot);
//出答案
return 0;
}