题意,给出被割断的n个树枝的长度;
求出其最小原长.
input
9
5 2 1 5 2 1 5 2 1
6
4
1 2 3 4
5
0
经典的一道深授,要经过多次减枝:
//第一次,从大到小判断短棒;即如(a,b,c)其中c=a+b;则总先判断c;
//第二次,y记录判断到第几根木棒,下一次选取木棒则从第几根开始.
//第三次,若判断第i根木棒失败,则不必判断与其相同长度的木棒.
//第四次,选取好原木棒后,若第一次选取木棒就失败,则直接退出.
同时再熟悉一下深搜的过程,深搜主要用在,搜索过程中需要不断的尝试,了解尝试的条件与尝试失败的条件;
一般格式:
在适当位置加上搜索成功条件
return true;
if(符合尝试条件)
标记vis【】=true
dfs();
(失败)尝试失败后条件与操作;
vis【】=false;
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100;
int vis[N];
int a[N];
int sum,n;
int cmp(int x,int y)
{
return x>y;
}
int dfs(int y,int mix,int p,int k) //第二次,y记录判断到第几根木棒,下一次选取木棒则从第几根开始.
{
int pp,i;
if(k*mix==sum) return 1; //结束条件
for(i=y+1;i<=n;i++)
{
if(!vis[i]&&p-a[i]>=0)
{
vis[i]=1;
if(p-a[i]==0)
{
pp=dfs(0,mix,mix,k+1);
}
else if(p-a[i]>0)
{
pp=dfs(i,mix,p-a[i],k);
}
vis[i]=0; //失败
if (y==0) return pp; //第四次,选取好原木棒后,若第一次选取木棒就失败,则直接退出.
else if (pp) return pp;
while(a[i]==a[i+1])i++; //第三次,若判断第i根木棒失败,则不必判断与其相同长度的木棒.
}
}
return 0;
}
int main()
{
int i,mix;
while(cin>>n,n)
{
sum=0;
memset(vis,0,sizeof(vis));
memset(a,0,sizeof(a));
for(i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
sort(a+1,a+n+1,cmp); //第一次,从大到小判断短棒;即如(a,b,c)其中c=a+b;则总先判断c;
int ans=sum;
for(i=a[1];i<=sum/2;i++)
{
mix=i;
if(sum%mix==0&&dfs(0,mix,mix,0))
{
ans=mix;
break;
}
}
cout<<ans<<endl;
}
return 0;
}