HDU 1455 Sticks(回溯,减枝很巧妙)
来源:互联网 发布:上海巴斯德研究所 知乎 编辑:程序博客网 时间:2024/06/06 07:33
题目地址:点击打开链接
题意:小明拿来几根相同长度的棍子,然后把这些棍子截成好几节,问最后能拼成几根长度相同的棍子(要求这些棍子的长度最小)
思路:和HDU1518相似,可以看本博客,那道题解写的比较详细,这不过这道题得在那道题上多加几个减枝才能A
AC代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <cstring>#include <climits>#include <cmath>#include <cctype>using namespace std;int a[70];bool flag;int n,l;int length;int visit[70];void dfs(int start,int sum,int now){ int i; if(flag) return; if(sum == l) { flag = true; return; } for(i=start; i<n; i++) { if(!visit[i]) { if(now + a[i] == length) { visit[i] = 1; dfs(0,sum+1,0); visit[i] = 0; } else if(now + a[i] < length) { visit[i] = 1; dfs(i+1,sum,now+a[i]); visit[i] = 0; if(now == 0)//减枝1 return; while(a[i] == a[i+1])//减枝2,相同长度的就不用再搜了 i++; } } }}int main(){ int i; while(scanf("%d",&n) && n) { flag = false; int sum = 0; for(i=0; i<n; i++) { scanf("%d",&a[i]); sum += a[i]; } sort(a,a+n); for(i=a[n-1]; i<=sum; i++)//最后组成的边肯定大于等于最长边,枚举边比较好,枚举条数不好,原因看超时代码下面的解释 { if(sum % i == 0) { memset(visit,0,sizeof(visit)); l = sum / i; length = i; dfs(0,0,0); if(flag) { printf("%d\n",i); break; } } } } return 0;}
因为这道题只求可能情况,不是求种类数,减枝方法还是挺多的(1)只要求可能情况,所以可以提前排序(由大到小或者由小到大都无所谓),每次只选它后面的,举个例子啊,1,6,2,5;一看边长就是7,从1搜到6,或者从6搜到1,都能说明这条边存在,所以只搜1到6就可以了,然后再看减枝1,这个特别巧妙,我再举个例子啊,边长为1,6,9,2,4,10;这个一看每条边就是16,减枝1之所以成立,是因为每条边都会用,所以当目前长度为0时选一个就行,而当长度为0时,选一个可能构不成边,例如这个例子,按选一个的思想,他会选1,4,6,显然是错误的,所以第一个没有组合情况,以后的都会有组合情况
超时代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <cstring>#include <climits>#include <cmath>#include <cctype>using namespace std;int a[70];bool flag;int n,l;int length;int visit[70];void dfs(int start,int sum,int now){ int i; if(flag) return; if(sum == l) { flag = true; return; } for(i=start; i<n; i++) { if(!visit[i]) { visit[i] = 1; if(now + a[i] == length) { dfs(0,sum+1,0); } else if(now + a[i] < length) { dfs(i+1,sum,now+a[i]); } visit[i] = 0; } }}int main(){ int i,j; while(scanf("%d",&n) && n) { flag = false; int sum = 0; int min1 = 1000000000; for(i=0; i<n; i++) { scanf("%d",&a[i]); sum += a[i]; if(a[i] < min1) min1 = a[i]; } sort(a,a+n); for(i=sum; i>=min1; i--) { if(sum % i == 0) { memset(visit,0,sizeof(visit)); l = i; length = sum / i; for(j=0; j<n; j++) { if(a[j] > length) break; } if(j == n) { dfs(0,0,0); if(flag) { printf("%d\n",length); break; } } } } } return 0;}
其实我这个代码写的还是比较逗的,最小值排序一下就能出来,我却特意求了一下,然后枚举的条数,结果里面多加了一个for循环减枝,并且for循环的范围大,枚举边的范围是从最大边到sum,而枚举条数是从最小边到sum,这样不就是把时间搞的更长了么
0 0
- HDU 1455 Sticks(回溯,减枝很巧妙)
- HDU 1518 Square(回溯搜索,减枝很巧妙啊)
- HDU 1455 Sticks(分组)
- [UVA 307] Sticks (DFS回溯 + 剪枝)
- UVA - 307 Sticks(回溯+剪枝)
- uva 307 Sticks(回溯剪枝)
- hdu 1455 Sticks (dfs 经典剪枝)
- hdu 1455 Sticks(经典DFS)
- HDU 1455——Sticks(神棍)
- hdu 1455(Sticks 经典深搜)
- hdu 1455 Sticks(DFS+剪枝)
- hdu 1455 Sticks(DFS+剪枝)
- HDU - 1455 Sticks(深搜+剪枝)
- HDU 1455 Sticks(dfs+强剪枝)
- hdu 1455 sticks (dfs+枝剪)
- HDU 1455 Sticks
- Hdu 1455 Sticks
- hdu 1455 Sticks
- 近期学习的几大PS神技
- Form表单中method="post/get'的区别
- Python 基础——list的成员方法
- 关于oracle数据库的隐式转换的操作
- 叉姐的魔法训练小结(未完结)
- HDU 1455 Sticks(回溯,减枝很巧妙)
- JPA spring @Entity @Table 概述
- C++学习笔记(一)——内存分配问题
- 【果然叼】这款软件怎么实现的,太牛逼了吧?
- awt和swing的区别
- JPA各种注解
- 背包问题
- shell编程之if判断的总结
- iptables