洛谷 P1120 小木棍 [数据加强版]
题目描述
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。
现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。
给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
输入输出格式
输入格式:
输入文件共有二行。
第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤65
(管理员注:要把超过50的长度自觉过滤掉,坑了很多人了!)
第二行为N个用空个隔开的正整数,表示N根小木棍的长度。
输出格式:
输出文件仅一行,表示要求的原始木棍的最小可能长度
输入输出样例
说明
2017/08/05
数据时限修改:
-#17 #20 #22 #27 四组数据时限500ms
-#21 #24 #28 #29 #30五组数据时限1000ms
其他时限改为200ms(请放心食用)
思路:各种优化的搜索。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,m,mx,sum; int num[65],vis[65]; int cmp(int a,int b){ return a>b; } void dfs(int ans,int s,int goal,int now){ if(s*goal==sum){ printf("%d",goal); exit(0); } if(sum-ans<num[m]) return ; if(ans==goal){ dfs(0,s+1,goal,1);return ; } for(int i=now;i<=m;i++){ if(!vis[i]&&num[i]+ans<=goal){ vis[i]=1; dfs(ans+num[i],s,goal,i+1); vis[i]=0; if(ans+num[i]==goal||ans==0) break; while(num[i]==num[i+1]) i++; } } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ int x;scanf("%d",&x); if(x>50) continue; num[++m]=x;sum+=x; mx=max(mx,x); } sort(num+1,num+1+m,cmp); for(int i=mx;i<=sum/2;i++) if(sum%i==0) dfs(0,0,i,1); printf("%d",sum); }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。