给你一堆棒子,这些棒子是你从一堆一样的棒子折断而来的,
现在你忘记了是从那一堆一样的棒子的长度,让你写一个程序,求最短的长度。
思路:
首先这个棒长肯定是和的约数,且大于最大值。
然后是sort一下棒子长度从大到小(我也不知道为啥可行)
最后就是一个判重剪枝:
注意判重剪枝,是对相同情况的剪枝,这个相同情况就是要非常相同!
这里代码那个!vis[i]很有体会啊;
//#include <bits/stdc++.h> #include<iostream> #include<cstdio> #include<queue> #include<math.h> #include<string.h> #include<algorithm> using namespace std; typedef long long LL; typedef pair<int,int> PII; int n,a[65]; int multi[550],sum; bool cmp(int x,int y) { return x>y; } int solve(int x,int temp) { int num=0; int q=(int)sqrt((double)x); for(int i=1;i<=q;i++) if(x%i==0){ if(i>=temp) multi[num++]=i; if((x/i)>=temp) multi[num++]=x/i; } return num; } bool vis[65]; int flag; void DFS(int num,int len,int cur) { if(flag==1) return; if(num*len==sum) { flag=1; return; } int tempcur=cur,tempnum=num; if(cur==0) { int x=1; while(vis[x]) x++; cur+=a[x]; if(cur==len) { cur=0; num++; } vis[x]=1; DFS(num,len,cur); vis[x]=0; cur=tempcur; num=tempnum; return; } for(int i=1;i<=n;i++) { if(vis[i]||cur+a[i]>len) continue; if(i>1&&a[i-1]==a[i]&&!vis[i-1]) // !vis[i-1]要保证相同情况; continue; cur+=a[i]; if(cur==len) { num++; cur=0; } vis[i]=1; DFS(num,len,cur); vis[i]=0; num=tempnum; cur=tempcur; } } int main() { while(scanf("%d",&n)&&n){ int tmx=0; sum=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); sum+=a[i]; tmx=max(tmx,a[i]); } sort(a+1,a+n+1,cmp); int num=solve(sum,tmx); sort(multi,multi+num); flag=0; for(int i=0;i<num;i++) { memset(vis,0,sizeof(vis)); DFS(0,multi[i],0); if(flag==1) { printf("%d ",multi[i]); break; } } } return 0; }