Sticks
来源:互联网 发布:洛阳正扬软件 编辑:程序博客网 时间:2024/06/05 18:53
木棒
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 139038 Accepted: 32776
Description
乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。
Input
输入包含多组数据,每组数据包括两行。第一行是一个不超过64的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。
Output
为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。
Sample Input
9
1.看到这个题,就是要把小棒一个个进行比较,看能不能恢复若干个原棒。但这样枚举效率太低。
2.这里用深度优先搜索来遍历(递归实现)速度较快。
3.假设原始木棒的长度已定,那么由若干小棒来组成一根这样的棒后,其它的原棒将不再由这些已经用过的小棒来拼接了。我们可以设置book数组来标记这些已经“成功”拼接的木棒,而不是已经用过的木棒。
4.那么原始木棒长度有多长,不至于从0一直往后试探吧?这样太麻烦。因为长度最小的原棒,它的长度不会比目前最大的小棒还短。长度最大的原棒的长度不会比所有小棒的长度和还长。这样范围就确定了。
5.我们用深搜用什么参数呢?
首先应该是对某个可能存在的长度(原棒长)进行试探性的验证,看是否能由这所有的小棒组成。那么这个参数是必须的,记为len。
然后,每当“成功”接收一根小木棒(前提是这根小木棒的接收能导致一根完整的木棒被拼出,而不是暂时被接收),那么拼接好的小木棒数就会相应加1.这个参数很重要(记为s)。
再就是对我们要试探的原木棒可能取值,每当它成功接收一根小木棒,还需要用来拼接一根原木棒的长度就会减小。这也是搜索过程必须知道的量,当它减小到0时,说明一根原木棒拼接完成,它将重新被赋值为len,从而进行下一根木棒的搜索。可知这个参数同样很重要(记为remain_len)。
6.由于过程中要确定某根小棒是否确定成功被接收,它就得提前预知加入这根小棒后其它的小木棒能不能匹配成功,就叫要求在遍历某个小木棒时,对其后的木棒进行递归搜索(深搜的特点),若能匹配成功,则标记当前小木棒为用过,可以直接返回(试探成功);若不能匹配,说明此棒目前不可用,将标记取消,待下一次搜索用。若当前木棒不可用,那么与这根小木棒长度相同的木棒也将不可用,直接跳过(剪枝),而且若这个小木棒的长度刚好是reamins_len的长度,那么更能说明后面的不能匹配了(匹配成功是所有的小木棒都被使用并可以满足条件,所以先使用这一根遍历和先使用其他的是一样的效果),因为如此合适的小棒被接收都不能导至试探成功,后面的小棒更不可能,直接返回0(试探失败 )(剪枝)。还有就是如果len=remains_len(说明这是新一根原棒,还没有进行匹配,与前一种情况类似),而在预先判断匹配与否时已经判断不能匹配,这样都不能匹配,那么说明以后都不能匹配了(这就是深搜的效果了)。返回0(试探失败)(剪枝)。
7.当remains_len=0&&num=0说明能用的棒已经没有,而且拼成一根原棒还需的长度为0,只能表示原棒已经完整的由这所有的小棒拼接出来。此时只需返回len(试探成功),这个操作应该放在函数最前。
8.如果深搜完成,仍未返回试探成功,到了函数的最后,只能说明这个试探失败。直接返回0.
9.为了让用过但没有被成功接收的小木棒再次利用,所以函数里对每个小棒进行一次搜索。以让这些漏网的小木棒或许能被再次利用。
10.注意:当换一个原木棒长度进行试探时,要置visited为0,否则会与上次搜索混在一起
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <algorithm>#include <cstring>using namespace std;int a[66],book[66],n,len;bool cmp(int a,int b){return a>b;}int dfs(int s,int remain_len){int i; if(remain_len==0&&s==n+1) return 1; else if(s>n) return 0; else if(remain_len==0) remain_len=len; for(i=1;i<=n;i++) { if(book[i]) continue; if(remain_len>=a[i]) { book[i]=1; if(dfs(s+1,remain_len-a[i])) return 1; book[i]=0; //else//{if(remain_len==len||a[i]==len) break; while(a[i+1]==a[i]&&i+1<=n) i++;//} } } return 0;}int main(){int i,sum;while(~scanf("%d",&n)){if(n<=0) break;sum=0;for(i=1;i<=n;i++){scanf("%d",&a[i]);sum+=a[i];} sort(a+1,a+1+n,cmp);for(i=a[1];i<=sum;i++){if(sum%i==0){memset(book,0,sizeof(book));//每次设定新的len都需要初始化,很重要len=i;if(dfs(1,i)) break;}} printf("%d\n",len);} return 0;}
- Sticks
- sticks
- sticks
- sticks
- Sticks
- sticks
- Sticks
- Sticks
- Sticks
- Sticks
- Sticks
- Sticks
- Sticks
- Sticks
- Sticks
- sticks
- Sticks
- 1011 Sticks
- Java程序编译
- Java JDBC 学习
- Intel Media SDK之开发资源汇总(含Windows和Linux)
- PHP中的trait,interface和abstract
- 关于框架的相关问题
- Sticks
- Java开源工具iText生成PDF文件
- linux相关命令应用
- git push 每次都需要输入用户名和密码
- 直播主流的协议
- Linux中的用户、组和权限管理
- 课堂总结
- matplotlib tricks(一)—— 多类别数据的 scatter(cmap)
- ajax异步分页