【问题描述】
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过100。
现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。
给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
【样例输入】
9
5 2 1 5 2 1 5 2 1
【样例输出】
6
【解题思路】
这道题的核心思想就一个字,搜……首先找到最大的那一段,原始木棍的可能长度必定>=最大的那一段木棍的长度,所以我们从最大的那一段长度开始往木棍总长度搜,将木棍排序,定义f布尔型数组,用来存该木棍是否用过,由于最终必定每一根木棍都可以成为组成的一部分,因此我们只要碰到没用过的就搜即可,如果有一根无法组成,那就不是原始木棍的长度,搜下一个长度,详见代码。
【代码实现】
1 var a:array[0..100] of longint; 2 f:array[0..100] of boolean; 3 n,i,s,maxn,now,j:longint; 4 flag:boolean; 5 procedure sort(l,r: longint); 6 var 7 i,j,x,y: longint; 8 begin 9 i:=l; 10 j:=r; 11 x:=a[(l+r) div 2]; 12 repeat 13 while a[i]<x do 14 inc(i); 15 while x<a[j] do 16 dec(j); 17 if not(i>j) then 18 begin 19 y:=a[i]; 20 a[i]:=a[j]; 21 a[j]:=y; 22 inc(i); 23 j:=j-1; 24 end; 25 until i>j; 26 if l<j then 27 sort(l,j); 28 if i<r then 29 sort(i,r); 30 end; 31 function pd(sum,v:longint):boolean; 32 var i:longint; 33 begin 34 pd:=false; 35 if sum=now then 36 exit(true);//如果等于当前所搜的长度,就暂时是正确的,可以搜其他没有搜的木棍 37 if sum>now then 38 exit(false);//如果大于了,那么就剪枝,搜下一根木棍 39 for i:=v downto 1 do 40 if f[i] then 41 if pd(sum+a[i],i-1) then 42 begin 43 f[i]:=false; 44 exit(true); 45 end; 46 end; 47 begin 48 readln(n); 49 for i:=1 to n do 50 begin 51 read(a[i]); 52 s:=s+a[i]; 53 if a[i]>maxn then 54 maxn:=a[i]; 55 end; 56 sort(1,n); 57 for i:=maxn to s do//从最长的搜到总长 58 if s mod i=0 then 59 begin 60 now:=i; 61 flag:=true; 62 fillchar(f,sizeof(f),true); 63 for j:=n downto 1 do 64 if f[j] then 65 if not pd(0,j) then//凡是没有用过的木棍都要搜一遍,只要有一根不能组成就搜下一个长度 66 begin 67 flag:=false; 68 break; 69 end; 70 if flag then 71 begin 72 writeln(i); 73 halt; 74 end; 75 end; 76 end.
时间: 2024-12-25 07:27:47