题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1455
-----------------------------------------------------------------------------------
题意:给出一定数量的小木棒的长度,它是由等长的若干木棒随意砍断所得到的。对于给定的一组小木棒,请求出可能的原始木棒的最小长度。
思路:
1.首先降序排列,因为木棍越长,可能的约束越大。
2.木棍的总长度除以原来的木棍数量,一定整除,剪枝
3.原来木棍的长度,一定大于等于剪短后最长的木棍,剪枝
4.在搜索的时候,如果发现某根木棒不符合要求,那么跳过之后与其等长的木棍,剪枝
5.如果新组合的木棍无法组合成功,那么直接放弃搜索,回退到上一层,剪枝
6.如果已经成功组合了一部分木棍,剩下的无法组合成功,由于是降序排列,直接放弃,返回上一层,剪枝
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<cmath> #include<set> #include<list> #include<deque> #include<map> #include<queue> using namespace std; typedef long long ll; const double PI = acos(-1.0); const double eps = 1e-6; const int MAXN =60+5; int a[MAXN]; int used[MAXN]; int n,leng,last; int dfs(int rei,int ned) { if(rei==0&&ned==0) return 1; if(ned==0) ned=leng; int start=0; if(ned!=leng) start=last+1; for(int i=start;i<n;i++) { if(!used[i]&&a[i]<=ned){ if(i>0){ if(!used[i-1]&&a[i-1]==a[i]) continue; } used[i]=1; last=i; if(dfs(rei-1,ned-a[i])) return 1; else{ used[i]=0; if(ned==leng||a[i]==ned) return 0; } } } return 0; } int cmp1(int a,int b){ return a>b; } int main() { int i; while(~scanf("%d",&n)&&n!=0) { int tot=0; for(i=0;i<n;i++) { scanf("%d",&a[i]); tot+=a[i]; } for(int k=0;k<MAXN;k++) used[k]=0; sort(a,a+n,cmp1); for(leng=a[0];leng<=tot/2;leng++) { if(tot%leng) continue; if(dfs(n,leng)){ printf("%d\n",leng); break; } } if(leng>tot/2) printf("%d\n",tot); } return 0; }