hdoj 1455 && nyoj 293 && poj 1110 Sticks 【DFS + 剪枝 + 剪枝 + 剪枝 + 。。。+ 剪枝】
2015-06-21 14:04
531 查看
Total Submission(s): 7380 Accepted Submission(s): 2170
Problem Description
George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were
originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.
Input
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the
file contains zero.
Output
The output file contains the smallest possible length of original sticks, one per line.
Sample Input
Sample Output
把三个OJ题目做了之后自己要崩溃。。。 先是0ms过hdoj,nyoj,poj超时,再是2352ms过nyoj,poj超时,最后0ms过poj。。。
思路:剪枝点有5个 对应代码里面给出的剪枝1,剪枝2,剪枝3,剪枝4,剪枝5
1,当前木条匹配失败,后面和它等长度的不能再用了,这个比较好想;
2,木条要降序排列,因为越长的约束力越大,当用一堆较短的木条构成的长度接近平均长度时,你用更大去匹配显然不行,这样会白白浪费很多时间;
3,最最重要的一点:要想得到最后的解,匹配每一组的第一个木条必须要成功,因为第一个不成功后面就不用想了;
4,在匹配完一组时,继续下一组时匹配,若是失败直接返回,因为中间若断了,最后也不能成功;
5,这一剪枝不太重要,但是还是说一下吧:枚举长度时,从最大的开始枚举,这一点不解释自己想。
hdoj poj :0ms nyoj :2324 ms
AC代码
大神8ms代码:醉了醉了 实在忍不住看了下,大牛别不要怪我。。。
Sticks
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7380 Accepted Submission(s): 2170
Problem Description
George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were
originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.
Input
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the
file contains zero.
Output
The output file contains the smallest possible length of original sticks, one per line.
Sample Input
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0
Sample Output
6 5
把三个OJ题目做了之后自己要崩溃。。。 先是0ms过hdoj,nyoj,poj超时,再是2352ms过nyoj,poj超时,最后0ms过poj。。。
思路:剪枝点有5个 对应代码里面给出的剪枝1,剪枝2,剪枝3,剪枝4,剪枝5
1,当前木条匹配失败,后面和它等长度的不能再用了,这个比较好想;
2,木条要降序排列,因为越长的约束力越大,当用一堆较短的木条构成的长度接近平均长度时,你用更大去匹配显然不行,这样会白白浪费很多时间;
3,最最重要的一点:要想得到最后的解,匹配每一组的第一个木条必须要成功,因为第一个不成功后面就不用想了;
4,在匹配完一组时,继续下一组时匹配,若是失败直接返回,因为中间若断了,最后也不能成功;
5,这一剪枝不太重要,但是还是说一下吧:枚举长度时,从最大的开始枚举,这一点不解释自己想。
hdoj poj :0ms nyoj :2324 ms
AC代码
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int stick[65]; int n; int every;//每组木条应有长度 bool vis[65];//标记当前木条是否用过 int total;//应成组数 bool cmp(int a, int b)//剪枝2: 降序排列 { return a > b; } int DFS(int match, int len, int pos)//match已成组数 len当前组已配长度 pos当前搜索位置 { if(match == total)//已成组数 等于 应成组数 return 1; else { for(int i = pos; i < n; i++) { if(vis[i]) continue;//已经用过 if(len + stick[i] == every)//正好配成一组 { vis[i] = true; if(DFS(match+1, 0, 0)) return 1;//继续配对下一组 vis[i] = false;//下一组配失败 return 0;//剪枝4: 不用进行下面的匹配了 } if(len + stick[i] < every) { vis[i] = true; if(DFS(match, len+stick[i], i+1)) return 1; vis[i] = false; if(len == 0)//剪枝3: 匹配第一根木条就失败 后面的也不用匹配了 return 0; while(stick[i] == stick[i+1])//剪枝1: 匹配失败 后面与它同长度的也不行 ++i; } } } return 0; } int main() { int i, sum; while(scanf("%d", &n), n) { for(i = 0, sum = 0; i < n; i++) { scanf("%d", &stick[i]); sum += stick[i]; } sort(stick, stick+n, cmp); for(every = stick[0]; every <= sum; every++)//剪枝5:从最长的木条开始遍历每组可能长度 { if(sum % every) continue;//不能整除 total = sum / every;//应成组数 memset(vis, false, sizeof(vis)); if(DFS(0, 0, 0)) { printf("%d\n", every); break; } } } return 0; }
大神8ms代码:醉了醉了 实在忍不住看了下,大牛别不要怪我。。。
#include <stdio.h> #include <stdlib.h> #include <string.h> #define L 64 int cutnum; // 木棍的数量 int cutlen[ L ], totlen; // 木棍的各自长度,及总长度 int cmp( const void *pa, const void *pb) { return (*((int*)pb)) - (*((int*)pa)); } int orglen, orgnum; // 原始木棍的长度及其数量 int used[ L ]; // dfs 时标记某木棍是否已经被用于组装原始木棍 //int choice[ L ]; // 若搜索次数超过此值,则认为不可能成功 #define LIM 100000 int lim; // 尝试拼装某原始木棍, // 此次尝试之前, // 已经使用了 t 根木棍, // 已经拼装出了原始木棍的部分长度,剩余 c 长度需要拼装, // 此次尝试,只需要从第 b 根木棍开始。 int dfs(int c, int b, int t) { int i, prelen = -1; if ( --lim <= 0 ) { return 0; } if ( 0 == c ) { // 剩余长度为 0,则开始拼装下一根原始木棍, // 需扩大尝试的范围。 for ( i = 0; (i < cutnum) && (used[i]); ++i ) { } // 所有木棍都已经被用于拼装原始木棍, // 即尝试成功。 if ( i >= cutnum ) { //printf("i >= cutnum, t = %d\n", t); return 1; } used[ i ] = 1; //choice[ t ] = i; // 任一原始木棍中,必含有剩余木棍中最长的那根 if ( dfs(orglen-cutlen[i], i+1, t+1) ) { return 1; } used[ i ] = 0; return 0; } for ( i = b; i < cutnum; ++i ) { if ( (used[ i ]) || // 木棍没用过 (prelen == cutlen[i]) || // 此长度的木棍已经试过,不行,无需再试 (c < cutlen[i]) // 剩余长度能容纳此木棍 ) { continue; } used[ i ] = 1; //choice[ t ] = i; // 下次尝试从后面的木棍开始,前面的木棍无需考虑 if ( dfs(c-cutlen[i], i+1, t+1) ) { return 1; } prelen = cutlen[ i ]; used[ i ] = 0; // 存在一木棍刚好可以符合剩余长度,则不再尝试其它 if ( c == cutlen[ i ] ) { return 0; } } return 0; } int find(){ // 原始木棍长度必为总长度的约数 if ( 0 != totlen % orglen ) { return 0; } orgnum = totlen / orglen; memset(used, 0, sizeof(used)); lim = LIM; return dfs(0, 0, 0); } int main() { int i; while ( (1 == scanf("%d", &cutnum)) && (0 < cutnum) ) { totlen = 0; for ( i = 0; i < cutnum; ++i ) { scanf("%d", cutlen+i); totlen += cutlen[ i ]; } // 将木棍从长到短排序,然后从长到短搜索之 qsort(cutlen, cutnum, sizeof(cutlen[0]), cmp); /**//*for ( i = 0; i < cutnum; ++i ) { printf("-%d-", cutlen[ i ]); } printf("\n");*/ // 原始木棍长度必大于等于最长木棍长度, // 小于等于木棍总长度, // 从短到长枚举原始木棍长度。 for ( orglen = cutlen[0]; (orglen < totlen) && (! find()); ++orglen ) { } printf("%d\n", orglen); //if ( orglen != totlen ) { // for ( i = 0; i < cutnum; ++i ) { // printf("--%d--", choice[ i ]); // } // printf("\n"); //} } return 0; }
相关文章推荐
- iText5报表_页眉与页脚
- Guava学习笔记
- OSPF概述
- Git 分布式版本控制系统(四) ---分支管理
- Android Java 自定义异常
- 毕业季致青春
- 补发《超级迷宫》站立会议十
- 学习的目的和方法论(实战主义)
- ASP.NET MVC5--为数据库新增字段(涉及数据库迁移技术)
- alex教学视频登陆接口
- bottle框架学习(六)之错误与重定向
- JAVA 反射
- 权限表的设计
- 第15周项目2-二进制文件浏览器
- 平面最近点对问题(分治)
- cocos code ide中横竖屏切换
- 第15周项目1-用二进制文件处理学生成绩
- 树状数组(二维)例题 HDU2642——Stars
- 会做的,不如会说的
- Integer to Roman