题目描述 Description
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过100。
现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。
给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
输入描述 Input Description
输入文件共有二行。
第一行为一个单独的整数N表示看过以后的小木柜的总数,其中N≤60,第二行为N个用空个隔开的正整数,表示N跟小木棍的长度。
输出描述 Output Description
输出文件仅一行,表示要求的原始木棍的最小可能长度。
样例输入 Sample Input
9
5 2 1 5 2 1 5 2 1
样例输出 Sample Output
6
数据范围及提示 Data Size & Hint
N<=60
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 62 using namespace std; int a[MAXN],vis[MAXN]; int n,num,sum; void dfs(int x,int aum,int k,int fr){ if(k==x) k=0; if(sum-aum==0){ cout<<x<<endl; exit(0); } if(sum-aum<x&&k==0||sum-aum<a[n]) return ; for(int i=fr;i<=n;i++){ if(!vis[i]&&k+a[i]<x){ vis[i]=1; dfs(x,aum+a[i],k+a[i],i+1); vis[i]=0; } else if(!vis[i]&&k+a[i]==x){ vis[i]=1; dfs(x,aum+a[i],k+a[i],1); vis[i]=0; } } } int cmp(int a,int b){ return a>b; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); sum+=a[i];num=max(num,a[i]); } sort(a+1,a+1+n,cmp); for(int i=num;i<=sum;i++) if(sum%i==0) dfs(i,0,0,1); } /* 7 63 2 44 12 60 35 60 */
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 62 using namespace std; int a[MAXN],f[MAXN]; int n,num,sum; bool dfs(int now,int s){ if(s<0) return 0; f[now]=0; if(s==0) return 1; for(int i=now-1;i>=1;i--) if(f[i]&&dfs(i,s-a[i])) return 1; f[now]=1; return 0; } bool check(int x,int tot){ memset(f,1,sizeof(f)); for(int i=1;i<=tot;i++) if(!dfs(n+1,x)) return 0; return 1; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); sum+=a[i];num=max(num,a[i]); } sort(a+1,a+1+n); for(int i=num;i<=sum;i++) if(sum%i==0&&check(i,sum/i)){ cout<<i<<endl; return 0; } } /* 7 63 2 44 12 60 35 60 */