HDOJ.1342 Lotto (DFS)
Lotto [从零开始DFS(0)]
从零开始DFS
HDOJ.1342 Lotto [从零开始DFS(0)] — DFS思想与框架/双重DFS
HDOJ.1010 Tempter of the Bone [从零开始DFS(1)] —DFS四向搜索/奇偶剪枝
HDOJ(HDU).1015 Safecracker [从零开始DFS(2)] —DFS四向搜索变种
HDOJ(HDU).1016 Prime Ring Problem (DFS) [从零开始DFS(3)] —小结:做DFS题目的关注点
HDOJ(HDU).1035 Robot Motion [从零开始DFS(4)]—DFS题目练习
HDOJ(HDU).1241 Oil Deposits(DFS) [从零开始DFS(5)] —DFS八向搜索/双重for循环遍历
HDOJ(HDU).1258 Sum It Up (DFS) [从零开始DFS(6)] —DFS双重搜索/去重技巧
HDOJ(HDU).1045 Fire Net [从零开始DFS(7)]—DFS练习/check函数的思想
题意分析
给出k(6 < k < 13)个数字,要求从这k个数字中选出升序的6个数字,并且按照字典序输出全部的可能,给出的k个数字已经按照升序排列好。
乍一看以为是排列组合,怎么想也想不到是用dfs来解决。按照这个数字选或者不选的逻辑,以为是dp什么的。最后看了题解才知道用dfs的方法做,也算是长见识了。作为dfs的第一道题,好好写,纪念一下。
dfs一般采用递归写法,或许是相比于bfs更加好写吧,所以能用dfs写的都用dfs了。
既然是深度优先,思路就是沿着一条路一直走,直到走到死胡同,原路返回,返回到有多条道路的地方换其他路走。直到这条支路全部都访问过了,按照原路返回,回到起点,如果起点还有别的支路,那么继续访问,反之结束整个搜索过程。
(图1-1)
Tip:数字为访问顺序,红色代表前进的过程,蓝色代表返回的过程。这里可以看到,是永远先访问上边的节点,其次是下面的节点。
Tiip:故意画成树的样子,树也是一张图呀。
实际解题的时候不可能无所约束的搜索下去,原因之一是会超时(TLE),原因之二就是没有那个必要。那么就需要减小搜索的规模,俗称剪枝。个人的理解是,当搜索到某一步的时候,继续搜索下去的解,明显不满足题目的要求时,终止这次搜索。
(图1-2)
Tip:如图,绿色节点均为不满足题意的解,那么当我搜索到绿色箭头所指向的点的时候,就没必要继续往下搜索了,即后续的3、4、5、6、7、8步骤均为多余的。
Tiip:由此可见,当数据规模非常大的时候,剪枝可以显著提高程序运行的效率。有时候没剪枝T了,剪枝就AC了。
回到本题。对于给定数字,面临的选择就是选或者不选,是不是和上面的树逻辑上很相似。先上代码,揉碎了慢慢写。。
代码总览
/*
Title:HDOJ.1342
Author:pengwill
Date:2017-2-3
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int a[20],b[10],n;
void dfs(int num, int pos)
{
if(num == 7){
for(int i =1 ;i<num; ++i){
if(i == 1) printf("%d",b[i]);
else printf(" %d",b[i]);
}
printf("\n");return;
}
if(pos>n) return;
b[num] = a[pos];
dfs(num+1,pos+1);
dfs(num,pos+1);
}
int main()
{
int t = 0;
while(scanf("%d",&n) && n != 0){
if(t!=0) printf("\n");
for(int i = 1; i<=n; ++i) scanf("%d",&a[i]);
dfs(1,1);
t++;
}
return 0;
}
从main函数开始:
while(scanf("%d",&n) && n != 0){
if(t!=0) printf("\n");
for(int i = 1; i<=n; ++i) scanf("%d",&a[i]);
t++;
}
这里是数据的读入部分,题目要求每组数据中间要有空行,所以引入变量t。
那么关键就在于dfs函数。
void dfs(int num, int pos)
{
if(num == 7){
for(int i =1 ;i<num; ++i){
if(i == 1) printf("%d",b[i]);
else printf(" %d",b[i]);
}
printf("\n");return;
}
if(pos>n) return;
b[num] = a[pos];
dfs(num+1,pos+1);
dfs(num,pos+1);
}
dfs函数有2个形参,num和pos,乍一看不知道他们的作用,先姑且放着。
之后是对于num是否为7的一个判断。如果为7的话,进行一个输出,应该就是题目要求的输出,数组b中保存着结果。可见num应该是判断是否构成了6位的排列,当num为7递归调用dfs时,用return语句终止这次搜索。原因很简单,题目只需要我找6位排列数,干嘛找7位的。
这样的判断,叫做递归边界(如有错误请各位指正)。递归边界可以是判断是否找到了解,如果找到了一组可行的解,就不进行递归了。当然要具体问题具体分析。
向下看,是对pos是否大于n的判断,如果大于n也就终止搜索了。n表示的是每组数据数字的个数,根据这个也可以想到,应该是从n个数中选6个,如果现在的位置是n+1(数据中根本没有这个数),当然不符合题意,终止。接着是一个赋值语句,应该可以想到是选中a数组pos这个位置的数字,把它写到b的num这个位置。
下面关键来了:
dfs(num+1,pos+1);
dfs(num,pos+1);
现在已经选中了a数组pos位置的数字,如果选它的话,那么就看下一位置选谁(这个位置是相对于数组b而言的),如果不选这个数字,那么对于这一位置,我们看看a数组下一个数字选还是不选。
(图1-3)
Tip:原谅我糟糕的画图技术
(图1-4)
如图所示,对于a中某一个数,有选或者不选2中选择(蓝色代表选,红色代表不选),组成了这样一颗树,直到num==7的是,结束搜索。
由此可以总结出dfs大概的函数模型
void dfs( 参数 )
{
// 递归边界
// 可以是检查是否满足解的要求
// 完成某系动作
// 继续递归调用dfs
}
这里只是皮毛啊,要想深入学习,多做题吧!
传送门:
HDOJ.1342 Lotto (DFS)的更多相关文章
- hdoj 1342 Lotto【dfs】
Lotto Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- Lotto(dfs)
Lotto Time Limit : 2000/1000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other) Total Submis ...
- hdoj - 1342 Lotto
Problem Description In a Lotto I have ever played, one has to select 6 numbers from the set {1,2,... ...
- LeetCode Subsets II (DFS)
题意: 给一个集合,有n个可能相同的元素,求出所有的子集(包括空集,但是不能重复). 思路: 看这个就差不多了.LEETCODE SUBSETS (DFS) class Solution { publ ...
- LeetCode Subsets (DFS)
题意: 给一个集合,有n个互不相同的元素,求出所有的子集(包括空集,但是不能重复). 思路: DFS方法:由于集合中的元素是不可能出现相同的,所以不用解决相同的元素而导致重复统计. class Sol ...
- HDU 2553 N皇后问题(dfs)
N皇后问题 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Description 在 ...
- 深搜(DFS)广搜(BFS)详解
图的深搜与广搜 一.介绍: p { margin-bottom: 0.25cm; direction: ltr; line-height: 120%; text-align: justify; orp ...
- 【算法导论】图的深度优先搜索遍历(DFS)
关于图的存储在上一篇文章中已经讲述,在这里不在赘述.下面我们介绍图的深度优先搜索遍历(DFS). 深度优先搜索遍历实在访问了顶点vi后,访问vi的一个邻接点vj:访问vj之后,又访问vj的一个邻接点, ...
- 深度优先搜索(DFS)与广度优先搜索(BFS)的Java实现
1.基础部分 在图中实现最基本的操作之一就是搜索从一个指定顶点可以到达哪些顶点,比如从武汉出发的高铁可以到达哪些城市,一些城市可以直达,一些城市不能直达.现在有一份全国高铁模拟图,要从某个城市(顶点) ...
随机推荐
- SQL 怎么实现模糊查询?
执行数据库查询时,有完整查询和模糊查询之分. 一般模糊语句格式如下: SELECT 字段 FROM 表 WHERE 某字段 LIKE 条件; 其中,关于条件,SQL提供了四种匹配模式: 一.%:表示零 ...
- Pycharm中查看方法的源码
方法1.鼠标放在函数上,Ctrl+B,看源码 方法2.将光标移动至要查看的方法处,按住ctrl 键,点击鼠标左键,即可查看该方法的源码.
- Jquery获取DOM绑定事件
获取到当前正在执行的事件: $('#testDive').bind('click', function(event){alert('event: ' + event.type)}); 获取所有绑定事件 ...
- Objective-C 第一个小程序
示例一 (类似C) //1.代码编写 //跟C语言一样,OC程序的入口依然是main函数,只不过写到一个.m文件中.比如这里写到一个main.m文件中(文件名可以是中文) #include <s ...
- 关于java获取网页内容
最近项目需求,做一些新闻站点的爬取工作.1.简单的jsoup爬取,静态页面形式: String url="a.atimo.cn";//静态页面链接地址Document doc = ...
- Laxcus大数据管理系统2.0(12)- 第十章 运行
第十章 运行 本章将介绍一些Laxcus集群基本运行.使用情况,结合图片和表格表示.地点是我们的大数据实验室,使用我们的实验集群.数据来自于我们的合作伙伴,软件平台混合了Windows和Fedora ...
- Bootstrap框架(图标)
Glyphicons 字体图标 所有可用的图标 包括250多个来自 Glyphicon Halflings 的字体图标.Glyphicons Halflings 一般是收费的,但是他们的作者允许 Bo ...
- ElasticSearch 论坛搜索查询语句
概述 研究论坛搜索如何综合时间和TF/IDF权重. 自定义权重计算的效率问题 数据结构 假设有一个论坛的搜索 字段包括: subject:标题 message:内容 dateline:发布时间 tag ...
- 收割大厂offer需要具备的条件
转载出处 本人也一直在关注互联网,觉得还是有些了解.互联网要求是越来越高了,竞争的人太多了,不过你不用担心,个人觉得,你到了中层的水平,拿二线offer应该没问题,人多也有人多的好处,我比别人多努力一 ...
- vue学习笔记(五):对于vuex的理解 + 简单实例
优点:通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护.使用vuex来引入外部状态管理,将业务逻辑切分到组件外,可以避免重复的从服务端抓取数据. 详情请参考官 ...