Language: Default简体中文 Sticks
Description George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him Input The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero. Output The output should contains the smallest possible length of original sticks, one per line. Sample Input 9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0 Sample Output 6 5 Source |
题意:给你紧跟棍子,问可能是哪几根相同的棍子截成的,求可能的棍子的最小值
很难的dfs,剪枝很重要,我也是看别人题解的⊙﹏⊙b汗,解释在代码中
#include<cstdio> #include<cmath> #include<algorithm> #include<iostream> #include<cstring> using namespace std; #define N 105 int a[N],len,n; int vis[N],sum; int cmp(int a,int b) { return a>b; } bool dfs(int pos,int temp,int cut) { if(cut==sum/len) //拼凑成功 return true; int i; for(i=pos;i<n;i++) { if(vis[i]==0&&temp+a[i]==len) { vis[i]=1; if(dfs(0,0,cut+1)) //记住前面可能有没有用到的棍子,所以从0开始(下一个dfs会寻找没有用到的棍子) return true; vis[i]=0;//我不是很清楚这个地方为什么变回来⊙﹏⊙b汗,如果5是所需的,不用5用3+2会不一样???? //还有不变回来会错,求路过大神指点迷津 return false; //这是因为上面5是所需,取5没用(接下来拼凑不成),那么取2+3也没有,因为2+3比5灵活 } else if(vis[i]==0&&temp+a[i]<len) { vis[i]=1; if(dfs(i+1,temp+a[i],cut)) return true; vis[i]=0; if(temp==0) return false; while(a[i]==a[i+1])//如果上一次取5没有,这次取5也拼不好 i++; } } return false; } int main() { int i; while(scanf("%d",&n),n) { sum=0; for(i=0;i<n;i++) { scanf("%d",&a[i]); sum+=a[i]; } sort(a,a+n,cmp); //降序 for(len=a[0];len<=sum;len++) //棍子不比比最长的段短 { if(sum%len) continue; //肯定是该长度的倍数 memset(vis,0,sizeof(vis)); if(dfs(0,0,0)) { printf("%d\n",len); break; } } } return 0; }