题意:一组等长的木棒,将它们随机的砍掉,得到若干根小木棍,
每一节小棍的长度都不超过50个单位。然后想把这些木棍拼接起来,恢复到裁剪前的状态,
但忘记了初始时有多少木棒以及木棒的初始长度。计算木棒的可能最小长度,每一节木棍的长度都用大于零的整数表示。
输入包含多组数据
这题很经典(有毒啊)
首先,对所有木棍排序(便于搜索)
然后倒着枚举初始木棒个数, 可以通过求平均算出木棒长度(最短),有解就输出(最优)
若当前个数无法被平均分,false
若当前答案比最长木棍小,false
然后开始搜索
详见代码
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; #define love_nmr 0 int n; int stick[100]; int ans; int ave; bool vis[100]; inline bool dfs(int num,int pos,int len) { if(num==n+1)return true; //全部搜完(合法了) for(int i=pos;i<=n;i++) { if(vis[i]) continue; //被用过 if(stick[i]+len<ans) //接上也比ans小(可用) { vis[i]=true; if(dfs(num+1,i+1,len+stick[i])) return true; //接上继续搜(标记) vis[i]=false; while(stick[i]==stick[i+1]&&i+1<=n)i++; //有跟他一样的跳过 } else if(stick[i]+len==ans) //正好接上 { vis[i]=true; if(dfs(num+1,1,0)) return true; //下一次从头开始 vis[i]=false; return false; } if(!len)return false; //没有能跟它拼的 } return false; } inline bool cmp(int a,int b) { return a>b; } int main() { while(~scanf("%d",&n)&&n) { ave=0; for(int i=1;i<=n;i++) { scanf("%d",&stick[i]); ave+=stick[i]; } sort(stick+1,stick+n+1,cmp); for(int i=n;i>=0;i--) { if(ave%i==0&&(ave/i)>=stick[1]) { ans=ave/i; // cout<<ans<<endl; memset(vis,0,sizeof vis); if(dfs(1,1,0)) { printf("%d ",ans); break; } } } } return love_nmr; }