小木棍 (codevs 3498)题解

【问题描述】

乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过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

小木棍 (codevs 3498)题解的相关文章

P1120 小木棍 [数据加强版] 题解

原题链接 简要题意: 把若干 \(\leq 50\) 的小木棍拼成若干长度相同的长木棍(一个小木棍也可以作为一根长木棍).求可以拼成的长木棍的最小长度. 暴力出奇迹 一看数据范围,\(n \leq 65\). 这一看就是指数级复杂度 我还没见过什么 \(O(n^5)\) 的算法.. 首先考虑 \(\texttt{dfs}\),枚举长木棍的长度,然后用 \(\texttt{dfs}\) 进行暴力枚举当前的小木棍分给哪一组(可以算出组数的),验证即可. 对这种最 卑劣 不太行的搜索,下面开始大力剪枝

[UVA307]小木棍 Sticks

题目大意:有一堆小木棍,把它们接成相同长度的小木棍,问结果的小木棍的最小长度是多少,多组数据 题解:$dfs$,各种剪枝. 卡点:无 C++ Code: #include <cstdio> #include <algorithm> #include <cstdlib> #define maxn 55 const int inf = 0x3f3f3f3f; int n, Min, Max, sum; int cnt[maxn]; bool halt; void dfs(i

1442:【例题3】小木棍

1442:[例题3]小木棍 题解 从最优性方面: 1.设所有木棍长度和为maxn,那么原长度(也就是需要输出的长度)一定能够被maxn整除,这样得到的木棍根数才是整数2.木棍原来的长度一定不小于所有木棍中最长的那根综上两点,可以确定原木棍的长度len在最长木棍的长度minx和maxn之间取值,且maxn能被len整除.所以在搜索原木棍的长度时,可以从砍过以后所有木棍中最长的长度开始,每次增加长度后,必须能整除maxn.这样可以有效优化程序. 从可行性方面: 1.短木棍更加灵活,长木棍受到的限制更

小木棍 爆搜剪枝

小木棍 爆搜剪枝 看了题解,用一个桶记录小木棍(很是机智,反正\(N\le50\)),然后就是爆搜剪枝了. 主要是注意一个优化思想:每次拼一个木棍时,一定先用大的去填再用小的去补. 递减遍历桶和下面这个最重要的剪枝都是这个优化思想 if(sum+i==per||sum==0) break; 连用大刚好填满这种最优方法都无法拼出,那更不用说先用小的去拼这种方法了. #include <cstdio> #include <cstdlib> #define MAX(A,B) ((A)&g

P1120 小木棍 [数据加强版]

题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度. 输入输出格式 输入格式: 输入文件共有二行. 第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤65 (管理员注:要把超过50的长度自觉过滤掉,坑了很多人了!) 第二行为N个用空个隔开的正整数,表示N根小木棍的长度. 输出格式: 输出文件仅一行,表示要求

洛谷P1120小木棍[DFS]

题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度. 输入输出格式 输入格式: 输入文件共有二行. 第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤60 (管理员注:要把超过50的长度自觉过滤掉,坑了很多人了!) 第二行为N个用空个隔开的正整数,表示N根小木棍的长度. 输出格式: 输出文件仅一行,表示要求

小木棍 [数据加强版]

题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度. 输入输出格式 输入格式: 输入文件共有二行. 第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤65 (管理员注:要把超过50的长度自觉过滤掉,坑了很多人了!) 第二行为N个用空个隔开的正整数,表示N根小木棍的长度. 输出格式: 输出文件仅一行,表示要求

【搜索】小木棍

[搜索]小木棍 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度. 输入 共有二行. 第一行为一个单独的整数N表示看过以后的小木柜的总数,其中N≤60,第二行为N个用空个隔开的正整数,表示N跟小木棍的长度. 输出 仅一行,表示要求的原始木棍的最小可能长度. 样例输入 9 5 2 1 5 2 1 5 2 1 样例输出

洛谷 P1120 小木棍

题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度. 输入输出格式 输入格式: 输入文件共有二行. 第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤60 (管理员注:要把超过50的长度自觉过滤掉,坑了很多人了!) 第二行为N个用空个隔开的正整数,表示N根小木棍的长度. 输出格式: 输出文件仅一行,表示要求