http://poj.org/problem?id=1011
题意:给你很多的碎木块,要你拼成一些等长的木棍,问这些木棍的最短长度是多少
一开始我用的是枚举要拼成多少木棍,搜索的时候把每根碎木块放到不同的木棍上,然后毫无人性的TLE了,这种索搜的局限主要就是不能提前知道能否拼出所枚举的长度,所以少了一个重要的剪枝。
思路:想加上上面的剪枝就必须依次填满每根木棍,出现不能填出所枚举的长度的时候就剪枝。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n;
int mapn[105];
bool vis[105];
bool cmp(int a, int b){
return a > b;
}
//从第pos根碎木快开始,已经累加的长度,枚举的长度,填第几根木棍,总共要填几根
bool Dfs(int pos, int sum, int lens, int st, int ed)
{
if(st == ed) //填完所有木棍
return true;
if(sum == lens) //填完当前木棍
return Dfs(0, 0, lens, st+1, ed); //填下一根
for(int i = pos, pre = 0; i < n; i++){
if(vis[i] || sum + mapn[i] > lens || pre == mapn[i]) //剪枝
continue;
pre = mapn[i]; //保存前一个,方便剪枝
vis[i] = true; //标记被用过了
if(Dfs(i+1, sum+mapn[i], lens, st, ed))
return true;
vis[i] = false;
if(pos == 0) //最重要的剪枝,表示第i根木棍和剩下的所有木棍都不能凑出一根长度为lens的木棍
return false;
}
return false;
}
int main()
{
while(cin>>n && n){
int sum = 0;
for(int i = 0; i < n; i++){
cin>>mapn[i];
sum += mapn[i];
}
sort(mapn, mapn+n, cmp);
for(int i = n; i > 0; i--){
memset(vis, false, sizeof(vis));
if(sum % i == 0 && Dfs(0, 0, sum/i, 0, i)){
cout<<sum/i<<endl;
break;
}
}
}
return 0;
}