解题思路:一个棍一个棍的组合,组合好第i根,再组合第i+1根,注意要剪好枝。
若前面的一个组合未能成功,当该组合再次出现时也不能成功。
#include<stdio.h>
int flag=0;
int flagall=0;
int a[65],b[65],max=0;
int main()
{
int n,i;
void search(int m,int k,int n);
int findmax(int n);
int sum(int n);
void sort(int n);
scanf("%d",&n);
while(n)
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
sort(n);
search(findmax(n),sum(n),n);
scanf("%d",&n);
for(i=0;i<65;i++)
a[i]=0;
}
return 1;
}
void sort(int n)
{
int temp;
for(int i=0;i<n;i++)
for(int j=0;j<n-i;j++)
if(a[j]<a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
int findmax(int n)
{
int max=0;
for(int i=0;i<n;i++)
if(a[i]>max)
max=a[i];
return max;
}
int sum(int n)
{
int s=0;
for(int i=0;i<n;i++)
s=s+a[i];
return s;
}
int findNotUsed(int start,int n)
{
int i;
for(i=start;i<n;i++)
if(!b[i])
break;
if(!b[i])
return i;
else
return n-1;
}
int find(int count)
{
for(int i=0;i<65;i++)
if(b[i]==count)
return i;
}
int findnostart()
{
for(int i=0;i<65;i++)
if(!b[i])
return i;
}
void isRight(int start,int m,int k,int count,int number,int n)
{
int index,form;
if(start>=n)
return ;
if(flag==number&&count==number+1)
{
flagall=1;
return ;
}
index=findNotUsed(start,n);
if(!b[index]&&index<n)
{
if(a[index]+k==m)
{
b[index]=count;
flag=count;
if(find(count)==max)
{
form=max;
max=findnostart();
isRight(0,m,0,count+1,number,n);
max=form;
}
b[index]=0;
flag=count-1;
}
else if(a[index]+k>m)
{
b[index]=0;
while(index+1<n&&a[index+1]==a[index])
index++;
isRight(index+1,m,k,count,number,n);
}
else
{
if(index!=0&&a[index-1]==a[index]&&!b[index-1])
{
while(index+1<n&&a[index+1]==a[index])
index++;
isRight(index+1,m,k,count,number,n);
}
else
{
b[index]=count;
isRight(index+1,m,k+a[index],count,number,n);
if(!flagall)
{
b[index]=0;
isRight(index+1,m,k,count,number,n);
}
}
}
}
}
void search(int m,int k,int n)
{
if(m==k)
{
printf("%d\n",m);
return ;
}
if(k%m==0)
{
for(int i=0;i<65;i++)
b[i]=0;
max=0;
isRight(0,m,0,1,k/m,n);
if(flagall)
{
flagall=0;
printf("%d\n",m);
}
else
search(m+1,k,n);
}
else
search(m+1,k,n);
}