如题:http://poj.org/problem?id=1011
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 125397 | Accepted: 29215 |
Description
Input
Output
Sample Input
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0
Sample Output
6 5
Source
思路:搜索
1.注意可以搜索的拼成后的小木棍的长度的范围, max(a[i]) <=l<=sum(a[i])且sum%i==0
2.3个重要剪枝
1.某根木棒的长度不能构成,则之后的相同长度的也不行
2.如果在构成某根木棒的第一段时最大的无法用上,那么直接不可能
3.如果把某段拿去构成木棒的最后一截后,剩下的无法完成,那么也不可能
3.搜索时用vis数组记录这根小木棍是否已经使用,避免重复使用。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
int a[70];
int vis[70];
int cmp(int x,int y)
{
return x>y;
}
int dfs(int total_len,int left_len,int left_num)
{
if(left_num==0&&left_len==0)
return 1;
if(left_len==0)
left_len=total_len;
int i;
for(i=0;i<n;i++)
{
if(!vis[i])
{
if(left_len>=a[i])
{
vis[i]=1;
if(dfs(total_len,left_len-a[i],left_num-1))
return 1;
vis[i]=0;
if(left_len==total_len||left_len==a[i])
break;
while(a[i]==a[i+1])
i++;
}
}
}
return 0;
}
int main()
{
// freopen("C:\\1.txt","r",stdin);
while(~scanf("%d",&n))
{
if(!n)
break;
int sum=0;
int i;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
sort(a,a+n,cmp);
for(i=a[0];i<=sum;i++)
{
if(sum%i==0)
{
memset(vis,0,sizeof(vis));
if(dfs(i,0,n))
break;
}
}
printf("%d\n",i);
}
}