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.基础部分 在图中实现最基本的操作之一就是搜索从一个指定顶点可以到达哪些顶点,比如从武汉出发的高铁可以到达哪些城市,一些城市可以直达,一些城市不能直达.现在有一份全国高铁模拟图,要从某个城市(顶点) ...
随机推荐
- 可靠UDP,KCP协议快在哪?
WeTest 导读 云真机已经支持手机端的画面投影.云真机实时操作,对延迟的要求比远程视频对话的要求更高(100ms以内).在无线网络下,如何更实时.更可靠的传输视频流就成了一个挑战.通过websoc ...
- 接口测试工具postman(六)添加变量(参数化)
1.添加全局变量并引用 2.通过设置请求前置配置变量 3.在Tests里面,把响应数据设置为变量 4.添加外部文件,引用外部文件中的变量和数据,此种场景就可以执行多次请求 1)配置文件,txt或者cs ...
- C++clock()延时循环
函数clock(),返回程序开始执行后所用的系统时间,但是有两个复制问题. 1.clock()返回时间的单位不一定是秒 2.该函数的返回类型在某些系统上可能是Long,也可能是unsigned lon ...
- 深度学习图像分割——U-net网络
写在前面: 一直没有整理的习惯,导致很多东西会有所遗忘,遗漏.借着这个机会,养成一个习惯. 对现有东西做一个整理.记录,对新事物去探索.分享. 因此博客主要内容为我做过的,所学的整理记录以及新的算法. ...
- opencv-学习笔记(4)-模糊
opencv-学习笔记(4)-模糊 本章要点: 4种模糊方式 2d卷积 Cv2.filter2D(‘图像对象’,‘目标图像这里直接设为-1即可’,kernal,anchor(-1,-1)) 一般后一个 ...
- NMAP-服务扫描
1.版本探测 2.扫描强度 共分1-9级,默认是7级,等级越高强度越高 同-sV一同使用 3.轻量扫描 等价于–version-intensity 2 4重量扫描 等价于–version-intens ...
- Keil ARM-CM3 printf输出调试信息到Debug (printf) Viewer
参考资料:http://www.keil.com/support/man/docs/jlink/jlink_trace_itm_viewer.htm 1.Target Options -> De ...
- ptrdiff_t类型
一.特性 1. 这是一种标准库类型 2. 是两个指针相减的结果的类型(因为差值可能为负值,所以是一种带符号类型) 3. 和size_t一样,ptrdiff_t也是一种定义在<cstddef> ...
- forward_list
一.特性 单向链表,只支持单向顺序访问(不支持快速随机访问),是C++11标准新增的类型 可类比于数据结构——单(向)链表 1. 没有size操作 forward_list为了追求性能,省去了size ...
- POJ 2823 (滑动窗口)
这道题最容易想到的是用朴素的做法,即 每滑动一次,就遍历一次窗口找出最大最小值,这样时间复杂度为O(n*k),由于题目数据比较大,这种做法肯定是超时的. 另外,根据书上的讲解,还可以采用优先队列来求解 ...