sticks hdu 1455 dfs+减枝
题意,给出被割断的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; }