这道题和poj的拯救少林神棍是一样的题目。
要用给出的小棍凑成等长的棍子,求能凑成的棍子的最小长度。
直观的包里思路就是枚举所有可能的长度,然后不停的测试小棍组合,先把小棍加入组合,然后不合适就推翻这一根小棍,再测试下一个小棍,直到推翻所有的小棍。
在枚举的时候,我们只需从最长的小棍长,枚举到小棍总长的一半就行了。然后如果再不符合的话,那么就说明所有小棍只能组合成一根棍子了。
我原先看过关于poj上拯救少林神棍这道题目的详细讲解。一个DFS搜索题,这里DFS共有四种剪枝方案:
开始我四种剪枝都写上了。但还是超时,无语了。
最后发现在DFS之外的main函数里有个剪枝我没有使用,要测试的长度一定要是总长度的因数,否则就没有必要测试这个长度。因为棍子是一样长的,每一根的长度当然要是总长度的因数才对。就是这个剪枝没有写导致我超时的。
#include<iostream>
#include<cstring>
#include<functional>
#include<algorithm>
using namespace std;
bool used[64];
int len[64],n,l,last;
bool dfs(int r,int m)
{
if(r==0&&m==0)
return true;
if(m==0)
m=l;
int start=0;
if(m!=l)
start=last+1;
for(int i=0;i<n;i++)
{
if(!used[i]&&len[i]<=m)
{
if(i>0)
{
if(used[i-1]==false&&len[i]==len[i-1])
continue;
}
used[i]=true;
last=i;
if(dfs(r-1,m-len[i]))
return true;
else
{
used[i]=false;
if(len[i]==m||m==l)
return false;
}
}
}
return false;
}
int main()
{
while(cin>>n)
{
if(!n)
break;
int total=0;
for(int i=0;i<n;i++)
{
cin>>len[i];
total+=len[i];
}
sort(len,len+n,greater<int>());
for(l=len[0];l<=total/2;l++)
{
if(total%l)//就是没写这个超时的。。
continue;
memset(used,false,sizeof(used));
if(dfs(n,l))
{
cout<<l<<endl;
break;
}
}
if(l>total/2)
cout<<total<<endl;
}
return 0;
}
hdu1455 dfs搜索之凑棍子,布布扣,bubuko.com
原文地址:http://blog.csdn.net/guodongxiaren/article/details/36492133