小木棒的经典题目,以前做了,但是这次在uva上做,就tle了
1.选小木棒要先排列,从大到小
2.选小木棒用dfs做,如果当前长度小于要求长度,标记好当前比较的小木棒。
如果等于,则把比较木棒从1开始即可。
3.一直tle了很久,后来发现原因,还要一个减枝
如果在当前这个循环下,这个长度仍为0,说明找不到木棒和它了,(才会一层层递归回来使它回到0)那么错误在上一个递归就产生了,不要继续在这个里面循环,直接递归退回上一层。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=200;
int det[maxn];
bool vi[maxn];
int n;
int suc;
bool cmp(const int &a,const int &b){return a>b;}
void check(int num,int len,int th,int nowlen,int k)
{if(th>num){suc=1;return;}
for(int i=k;i<=n;i++)
{
if(vi[i])continue;
int nlen=nowlen+det[i];
if(nlen==len)
{vi[i]=1;
check(num,len,th+1,0,1);
if(suc)return;
vi[i]=0;
return;
}
if(nlen<len)
{
vi[i]=1;
check(num,len,th,nlen,i+1);
if(suc)return;
vi[i]=0;
while(det[i+1]==det[i])i++;
}
if(nowlen==0)return;
}
}
int main(void)
{int sum;
while(scanf("%d",&n)&&n)
{sum=0;
for(int i=1;i<=n;i++)
{scanf("%d",&det[i]);
sum+=det[i];
}
sort(det+1,det+n+1,cmp);
// for(int i=1;i<=n;i++)printf("%d ",det[i]);printf("\n");
// printf("midgit=%d\n",midigit);
for(int i=det[1];i<=sum;i++)
{ if(sum%i)continue;
//printf("i=%d\n",i);
suc=0;
memset(vi,0,sizeof(vi));
check(sum/i,i,1,0,1);
if(suc){printf("%d\n",i);break;}
}
}
return 0;
}