Sticks
给定k根长度任意的小木棍,求能拼出的最短长度x;
考察:DFS+剪枝;
剪枝方案:
1.对于要拼的长度x,如果不是木棍总长的约数,无法拼;
2.最短长度x一定为大于等于给定木棍中的最长长度;
3.如果当前已经拼成了长度为len的木棍,对于一根长为m的木棍如果无法拼成功,那么对于以后的相同长度的木棍也无法拼成;
4.将木棍降序排序,因为长度较长的木棍的可变形较差,也就是说长度较长的木棍一般都是与较短的搭配,而不是较长的与较长的搭配;
5.可能会导致TLE的一点,当拼凑一根新的长度为x的木棍时,如果当前的第一根木棍无法与后面的木棍拼成功的话,那么该方案一定不可行,因为后面也一定无法用上该根木棍的;
Hint:然而没有使用第5点剪枝,能勉强过掉;920ms;

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int st[100+10];
int mark[100+10];
int n,cnt,ans,tot,pre,flag;
int cmp(int a,int b){
return a>b;
}
void dfs(int l,int rlen,int num)
{
if(num==pre)
{
flag=1;
return;
}
if(rlen==n) return;
if(flag) return;
for(int i=1;i<=n;i++)
{
if(!mark[i])
{
if(l+st[i]>cnt) return;
mark[i]=1;
if(l+st[i]!=cnt)
dfs(l+st[i],rlen+1,num);
else dfs(0,rlen+1,num+1);
mark[i]=0;
if(l==0) continue;
while(st[i+1]==st[i]) i++;
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
memset(st,0,sizeof st);
tot=cnt=pre=flag=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&st[i]);
tot+=st[i];
}
sort(st+1,st+n+1,cmp);
for(int i=st[1];i<=tot;i++)
{
if(tot%i==0)
{
memset(mark,0,sizeof mark);
cnt=i;
pre=tot/i;
dfs(0,0,0);
if(flag==1)
{
printf("%d\n",i);
break;
}
}
else continue;
}
}
return 0;
}