【DFS&&搜索剪枝】CODE[VS] 3498 小木棍
2016-11-10 11:31
561 查看
点击进入地狱
这个搜索做得比较早了….
11.1下午来机房开始搞这个暴搜,结果一直TLE&&WA
后来放了会没再管,11.3号早上又想了起来
然后就开始了悲惨的WA之路QAQ:
题是好题,是我太弱了…..
这道题的思路:
暴力枚举
我们枚举目标长度,当目标长度可以整除给出木棍长度之和的时候,我们再去判断这些木棍是否可以拼成该长度,这比枚举木棍根数要快并且更容易想到优化
(别问我怎么知道的,说多了都是泪)
但是裸暴力会超时,所以需要剪枝优化
1.首先很显然的一个剪枝,就是贪心,先将木棍从长到短排序,然后拼的时候先枚举长木棍的组合,因为长木棍限制更高,能够很快排除不少情况
2.然后我们可以在枚举目标木棍长度的时候,从给出木棍最长的开始到所有长度总和结束,因为显然目标木棍长度必然大于或等于数据给出的最长木棍长度
3.如果当前长度为0(第一层搜索),完成之后直接返回
4.在拼接木棍的的时候,相同长度的木棍之前用过,记录一下,下次直接continue
5…………………………………………………………………………………………..
代码:
THE END
By Peacefuldoge
http://blog.csdn.net/loi_peacefuldog
这个搜索做得比较早了….
11.1下午来机房开始搞这个暴搜,结果一直TLE&&WA
后来放了会没再管,11.3号早上又想了起来
然后就开始了悲惨的WA之路QAQ:
题是好题,是我太弱了…..
这道题的思路:
暴力枚举
我们枚举目标长度,当目标长度可以整除给出木棍长度之和的时候,我们再去判断这些木棍是否可以拼成该长度,这比枚举木棍根数要快并且更容易想到优化
(别问我怎么知道的,说多了都是泪)
但是裸暴力会超时,所以需要剪枝优化
1.首先很显然的一个剪枝,就是贪心,先将木棍从长到短排序,然后拼的时候先枚举长木棍的组合,因为长木棍限制更高,能够很快排除不少情况
2.然后我们可以在枚举目标木棍长度的时候,从给出木棍最长的开始到所有长度总和结束,因为显然目标木棍长度必然大于或等于数据给出的最长木棍长度
3.如果当前长度为0(第一层搜索),完成之后直接返回
4.在拼接木棍的的时候,相同长度的木棍之前用过,记录一下,下次直接continue
5…………………………………………………………………………………………..
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> using namespace std; int n,u; int osu; int len[105]; int totlen; int ans = 0x3ffffff; bool used[105]; inline int read() { char ch; int f = 1; int data = 0; while(ch < '0'||ch > '9') { ch = getchar(); if(ch == '-') f = -1; } do{ data = data*10+ch-'0'; ch = getchar(); }while(ch <= '9'&&ch >= '0'); return f*data; } bool cmp(const int a,const int b) { return a > b;} inline bool dfs(int s,int nowlen,int viv) { bool bj; if(nowlen == 0) bj = true; else bj = false; if(s == u) return true; for(int i = viv;i <= n;i++) { if(used[i] == 1) continue; if(nowlen + len[i] == osu) { used[i] = 1; if(dfs(s+1,0,0)) return true; used[i] = 0; return false; } else if(nowlen + len[i] < osu) { used[i] = 1; if(dfs(s,nowlen+len[i],i)) return true; used[i] = 0; if(bj == true) return false; } } return false; } int main() { n = read(); for(int i = 1;i <= n;i++) { len[i] = read(); totlen += len[i]; } sort(len+1,len+1+n,cmp); for(int i = len[1];i <= totlen;i++) { if(totlen%i == 0) { osu = i; u = totlen/i; memset(used,0,sizeof(used)); if(dfs(1,0,0)) { ans = min(ans,i); continue;} } } printf("%d\n",min(ans,totlen)); return 0; }
THE END
By Peacefuldoge
http://blog.csdn.net/loi_peacefuldog
相关文章推荐
- POJ 1011 Sticks CODE[VS] 3498 小木棍(DFS+剪枝优化)
- CodeVS3498 小木棍
- codevs 2033 邮票 (背包)&& codevs 1047 邮票面值设计 (dfs+dp)
- 搜索专题(DFS&&BFS&&剪枝)HDU 1728-逃离迷宫
- codevs 3498 小木棍
- 搜索+剪枝——CODEVS1288 埃及分数
- 【DFS】CODE[VS] 1018&&NOIP2000提高组T3 单词接龙 (日常刷题???)
- codevs 1116四色问题 DFS搜索
- CODE[VS] 1004 四子连棋 DFS搜索
- poj 1011 Sticks(经典搜索问题:DFS+剪枝)
- 51nod-1158 . 全是1的最大子矩阵 &&CODEVS-2491 玉蟾宫(枚举+单调栈 or dp)
- poj 1699 Best Sequence (搜索技巧 剪枝 dfs)
- 【动态规划】【记忆化搜索】【搜索】CODEVS 1262 不要把球传我 2012年CCC加拿大高中生信息学奥赛
- CodeVs 1135 && noip 2011 Day1-2 选择客栈
- VS2013推代码搜索插件Bing Code Search
- {CODEVS} 1018 单词接龙(DFS)
- pku 2488 A Knight's Journey (搜索 DFS)
- poj2488 A Knight's Journey 简单DFS 注意搜索步骤
- Code Vs 1169 传纸条 && 2008年NOIP全国联赛提高组
- 【技术文档】《算法设计与分析导论》R.C.T.Lee等·第6章 剪枝搜索方法