描述
Ben 喜欢做各种古怪的实验。这次他拿来一组等长的木棒,将它们随机地裁断,使得每一节木棒的长度都不超过50 个长度单位。然后他又想把这些木棒恢复到裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助他计算木棒的可能最小长度。每一节木棒的长度都用大于零的整数表示。
输入
输入包含多组测试数据,每组测试数据包括两行。第一行是一个不超过64 的整数N,表示裁截之后共有多少节木棒,当N为0时表示输入结束,不做任何处理。第二行是经过裁截后,所得到的各节木棒的长度。
输出
对于每组测试数据,请输出木棒的可能最小长度,每组输出占一行。
样例输入
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0样例输出
6 5题目来源
ben
解题思路:dfs+剪枝
木棒匹配首先应从最长的一段木棒开始匹配,因此首先要对木棒进行由大到小的排序 剪枝: 1.所选的木棒没有使用过 2.匹配过程如果不成功记录下该木棒的长度,下次匹配如果遇到此长度的木棒跳过 3.当前匹配的木棒长度一定小于总长度除以段数 4.如果第一段木棒没有匹配成功,则匹配失败5.如果匹配到最后一根没有成功,匹配失败
AC代码:
#include<iostream> #include<algorithm> #include<functional> using namespace std; int a[64],v[64],n,l; bool pin(int length,int i=0,int j=0,int action=0,int clength=0){ if(i==n) return true; else{ if(clength==length) return pin(length,i+1,i+2,0,0); if(action==0){ if(v[i]) return pin(length,i+1,i+2,0,0); else{ v[i]=1; if(pin(length,i,i+1,1,a[i])) return true; v[i]=0; return false; } } else{ while(j<n){ if(a[j]*(n-j)+clength<length) break; if(a[j]+clength>length){ j++; continue; } if(!v[j]){ v[j]=1; if(pin(length,i,j+1,1,clength+a[j])) return true; v[j]=0; j++; while(j<n&&a[j]==a[j-1]) j++; } else j++; } return false; } } } int main(){ while(scanf("%d",&n)!=EOF&&n){ l=0; for(int i=0;i<n;i++){ scanf("%d",&a[i]); l+=a[i]; } sort(a,a+n,greater<int>()); for(int i=n;i>0;i--) if(l%i==0&&l/i>=a[0]){ memset(v,0,sizeof(v)); if(pin(l/i)){ printf("%d\n",l/i); break; } } } return 0; }