1.枚举所有可能的所组成的长度
2.深搜
两个状态(a,b)
a:没有用过的棍的个数
b:当前要组成的棍还需要的长度
初始状态:(n,i)
终止状态:(0,0)
3.剪枝
未剪枝的dfs:
bool dfs(int a,int b)
{
if(a==0&&b==0)
{
return true;//dfs结束条件
}
if(b==0)
{
b=I;//一根棍子拼完
}
for(int i=0; i<n; i++)
{
if(!flag[i]&&b>=s[i])//如果棍子没有用过,且当前棍s[i]比待填的棍短,
{
flag[i]=1;//则尝试拼接
if(dfs(a-1,b-s[i]))//可以拼接,往后继续搜
return true;
else flag[i]=0;//当前棍拼接失败,标记取消,for尝试下一根棍
}
}
return false;
}
搜索题,充满了剪枝的
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int s[65],I,n,c;
bool flag[65];
bool dfs(int a,int b)
{
if(a==0&&b==0)
{
return true;
}
if(b==0)
{
b=I;
}
for(int i=0; i<n; i++)
{
if(!flag[i-1]&&s[i]==s[i-1])
continue;//与上一个未利用的棍有相同长度,同样不会符合,剪枝1
if(!flag[i]&&b>=s[i])
{
flag[i]=1;
if(dfs(a-1,b-s[i]))
{
return true;
}
else
{
flag[i]=0;
if(b==s[i]||b==I)
return false;//第一个根棍如果不能符合,则第一根放哪都不会符合,剪枝2
}
}
}
return false;
}
bool cmp(int aa,int bb)
{
return aa>bb;
}
int main()
{
while(cin>>n&&n)
{
int ttt=0;
int sum,maxn;
sum=0;
maxn=0;
memset(flag,0,sizeof(flag));
for(int i=0; i<n; i++)
{
cin>>s[i];
sum+=s[i];
if(s[i]>maxn)
maxn=s[i];
}
sort(s,s+n,cmp);//从大到小搜索剪枝3
for(int i=maxn; i<=sum/2; i++)//枚举剪枝4
{
I=i;
if(sum%i==0&&dfs(n,i))
{
ttt=1;
cout<<i<<endl;
break;
}
}
if(!ttt)//不要忘了这种情况
cout<<sum<<endl;
}
return 0;
}
应该还会有很多剪枝情况,嗯。。