poj 1011 Sticks
#include <iostream>
using namespace std;
int sticks[200],visited[200];
int flag,total;
int t,seg,num;
int cmp(const void* a,const void* b)
{
return (*(const int*)b)-(*(const int *)a);
}
void solve(int k,int sum,int cnt) //sum 是正在拼的木棍已经拼出的长度, k是从哪根碎木块开始拼,cnt是正在拼第几根木块
{
if(num==cnt)
flag=true;
else if(sum==seg)
solve(0,0,cnt+1); //如果本根木块拼完,拼下一根,再次从第0根木棍开始找
else
{
for (int pre=-1,i=k;i<t;i++) //枚举木棍
if(visited[i]!=1&&sticks[i]!=pre&&sticks[i]+sum<=seg) //如果这根木棍没被加过,并且它不等于前一块的长度
{
pre=sticks[i];
visited[i]=1;
solve(i+1,sum+sticks[i],cnt);
visited[i]=0;
//如果向下搜索不成功则回溯,visited[i]=0;若成功拼出原始长度则转到solve(0,0,cnt+1);从头开始拼,而visited[i]=0;未被执行
if(k==0||flag==1)return; //如果一直回溯到k==0说明无法拼出原始木棍
}
}
}
int main()
{
int i,max=0;
while(scanf("%d",&t)&&t)
{
total=0;
flag=0;
max=0;
for (i=0;i<t;i++)
{
scanf("%d",&sticks[i]);
if(max<sticks[i])
max=sticks[i];
total+=sticks[i];
}
qsort(sticks,t,sizeof(sticks[0]),cmp); //这里如果用sort就TLE了
for(seg=max;seg<=total;seg++)
{
if(total%seg!=0)
continue;
num=total/seg;
memset(visited,0,sizeof(visited));
solve(0,0,0);
if(flag)
break;
}
printf("%d\n",seg);
}
return 0;
}