题意:
有一堆木棒是由同一长度的木棒切割出来的,求最小可能的初始木棒长度。
思路:
这道题的关键在于如何确定某一长度的木棒能够满足条件。用到dfs,但是因为TLE需要多次的剪枝。
1. 初始木棒可选长度一定是木棒长度和的约数,同时一定大于任意一根木棒的长度;
2. 将木棒降序排序,因为较长的木棒比较不容易找到合适的匹配木棒来凑;
3. 当前木棒如果不能满足条件,和它长度相同的木棒也一定不能满足条件;
4. 如果递归到一个木棒时总长度为0,即该木棒为选择的第一根,从这跟木棒递归结束进去不能满足条件,直接break,因为必须保证每一根木棒都能搭配成功,当前木棒作为第一根仍无法搭配成功就说明之前的木棒选择有问题,直接break。但是注意这里不能判断为目标长度选择不正确而全盘否定,因为之前的木棒选择会影响之后的搭配,所以即便该木棒作为第一根仍无法匹配成功,不代表它永远不能,在该木棒之前可能选择了不合适的匹配。
64 40 40 30 35 35 26 15 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 43 42 42 41 10 4 40 40 40 40 40 40 40 40 40 40 40 40 40 40 25 39 46 40 10 4 40 40 37 18 17 16 15 40 40 40 40 40 40 40 40代码实现:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX = 100;
bool cmp(const int& a,const int& b){
return a>b;
}
int N;
int res;
bool flag;
bool fail;
int num[MAX];
bool visit[MAX];
void dfs(int deep,int sum,int pos);
int main(){
while( scanf("%d",&N) != EOF ){
if( N == 0 ){
break;
}
res = -1;
int tmp = 0;
flag = false;
fail = false;
for( int i = 0; i < N; i++ ){
scanf("%d",&num[i]);
tmp += num[i];
}
sort(num,num+N,cmp);
memset(visit,false,sizeof(visit));
for( int i = num[0]; i <= tmp; i++ ){
if( tmp%i == 0 ){
fail = false;
res = i;
visit[0] = true;
dfs(0,num[0],0);
visit[0] = false;
if( flag == true ){
break;
}
}
}
printf("%d\n",res);
}
return 0;
}
void dfs(int deep,int sum,int pos){
if( deep == N-1 ){
flag = true;
return ;
}
if( flag==true ){
return ;
}
if( sum == res ){
sum = 0;
pos = -1;
}
for( int i = pos+1; i < N; i++ ){
if( visit[i] == true ){
continue;
}
if( sum+num[i] <= res ){
visit[i] = true;
dfs(deep+1,sum+num[i],i);
visit[i] = false;
if( flag == true ){
return ;
}
if( sum == 0 ){
break;
}
while( num[i] == num[i+1] ){
i++;
}
}
}
return ;
}