HDOJ(HDU).1015 Safecracker [从零开始DFS(2)]

从零开始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函数的思想

题意分析

首先默认有个字母到数字的映射,A=1,B=2,C=3 …… Z=26,给出你一个目标数字target,然后给出一串字母,要求从这些字母中选取5个数字vwxyz,满足

v - w^2 + x^3 - y^4 + z^5 = target。可能有多组解,只输出字典序最大的那个。

嗨呀一看到这道题,是否有种似曾相识的感觉。很像HDOJ.1342 Lotto [从零开始DFS(0)]这道题。题目的大意都是选数字,满足某种要求。我们分析一下这道题和HDOJ.1342的异同:

1.HDOJ.1342给出的数据是有序的因此我们直接想选择/不选,找到解的时候就直接是按照字典序由小到大输出的。

但是本题给出来的字母的序列是无序的因此想要只输出一组字典序最大的解就需要按照降序排序,然后再处理。

2.HDOJ.1342中每个数字面临的情况是选或者不选,只要位数凑够6即可。但是此题不能按照这样的想法,因为按照顺序判定选或者不选的时候,这样可能丢解。举个例子:

给定的字母序列(已经按照降序排列好):ZXVUNMDBA

按照之前的思路,我们只需要依次判定Z选/不选,X选/不选……A选/不选。把选定的5个数字依次填在v, w, x, y, z的位置上。但是如果

ZBVUN是一组解的话,按照上面的思路根本搜索不到。

Tip:B明显比V小

解决方法:想起HDOJ.1010 Tempter of the Bone [从零开始DFS(1)]中的4方向搜索的环节了吗?只需要对dfs函数稍加改动,再用visit数组判断是否选择过此数字即可。

HDOJ.1010 中的四方向搜索:

    for(int i = 0;i<4;++i){
if(!visit[x+spx[i]][y+spy[i]]&&!judge){
dfs(x+spx[i],y+spy[i],s+1);
visit[x+spx[i]][y+spy[i]] = false;
}
}

Tip: 我们按照这样式的,采用for循环来实现。

上代码,掰开了揉碎了慢慢来。。

代码总览

/*
HDOJ.1015
Author:pengwill
Date:2017-2-5
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char a[15], b[10];
int visit[15];
int n,num,len;
bool judge = false; bool cmp(char a, char b)
{
return a>b;
}
void init()
{
len = strlen(a);
judge = false;
memset(visit,0,sizeof(visit));
sort(a,a+len,cmp);
for(int i = 0;i<len;++i){
a[i] = a[i] -'A' + 1;
}
}
void lnit()
{
for(int i = 0;i<5;++i)
b[i] = b[i]+'A'-1;
}
bool check()
{
if(n == b[0] - b[1]*b[1] + b[2]*b[2]*b[2] - b[3]*b[3]*b[3]*b[3] + b[4]*b[4]*b[4]*b[4]*b[4]){
judge = true;
return true;
}else return false;
}
void dfs(int depth)
{
//递归边界
if(judge) return;
if(depth == 5) {check(); return;}
for(int i = 0;i<len;++i){
if(!visit[i]&&!judge){
b[depth] = a[i];
visit[i] = 1;
dfs(depth+1);
visit[i] = 0;
}
}
}
int main()
{ //freopen("in.txt","r",stdin);
while(scanf("%d %s",&n,a)&& !(n==0 && !strcmp(a,"END"))){
init();
dfs(0);
lnit();
if(judge)printf("%s\n",b);
else printf("no solution\n");
}
return 0;
}

main函数中完成了数据的读入,init函数把字符数组a中的字母转变成数字,lnit函数在最后输出的时候把数组b中的答案又转变成了字母,check函数就是检查是否是满足题目要求的解。关键在dfs函数。

void dfs(int depth)
{
//递归边界
if(judge) return;
if(depth == 5) {check(); return;}
for(int i = 0;i<len;++i){
if(!visit[i]&&!judge){
b[depth] = a[i];
visit[i] = 1;
dfs(depth+1);
visit[i] = 0;
}
}
}

不要忘记题目要求:找到一组字典序最大的解即可。首先是递归边界,如果找到了解(judge为真),停止递归;亦或是当depth为5(代表找到了5个数字)的时候,用check函数判断一下是否满足题目要求。若都不满足递归边界,继续搜索。

下面的for循环非常像dfs地图的四向搜索,但是len指的是数据中给定的字母序列的长度。那么就指,下一个搜索的目标要在所有的字母序列中找,哪些可以作为搜索目标呢?首先就是这个字母没有被选定过(!visit[i] )并且现在解还没有找到(!judge)。 进入if后,首先把数组b中depth的位置赋值为a[i],代表我数组b选定了你a中i这个位置的数字(或者说是字母),并且在visit中置为选择过了,dfs(depth+1)继续寻找下一个位置的搜索目标。别忘了最后把visit[i]置为0(无后效性)。

相比前边2题,此题的收获就在于:原先的地图四向搜索,也可以变成这样从几个字符,数字中寻找可行的解。活学活用,非常重要呀!

HDOJ(HDU).1015 Safecracker (DFS)的更多相关文章

  1. HDOJ/HDU 1015 Safecracker(深搜)

    Problem Description === Op tech briefing, 2002/11/02 06:42 CST === "The item is locked in a Kle ...

  2. HDOJ/HDU 1015 Safecracker(枚举、暴力)

    Problem Description === Op tech briefing, 2002/11/02 06:42 CST === "The item is locked in a Kle ...

  3. hdu 1015 Safecracker 水题一枚

    题目链接:HDU - 1015 === Op tech briefing, 2002/11/02 06:42 CST === "The item is locked in a Klein s ...

  4. HDU 1015 Safecracker【数值型DFS】

    Safecracker Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  5. HDU 1015 Safecracker (DFS)

    题意:给一个数字n(n<=12000000)和一个字符串s(s<=17),字符串的全是有大写字母组成,字母的大小按照字母表的顺序,比如(A=1,B=2,......Z=26),从该字符串中 ...

  6. hdu 1015(DFS)

    Safecracker Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  7. HDU 1015 Safecracker

    解题思路:这题相当诡异,样例没过,交了,A了,呵呵,因为理论上是可以通过的,所以 我交了一发,然后就神奇的过了.首先要看懂题目. #include<cstdio> #include< ...

  8. ZOJ 1403&&HDU 1015 Safecracker【暴力】

    Safecracker Time Limit: 2 Seconds      Memory Limit: 65536 KB === Op tech briefing, 2002/11/02 06:42 ...

  9. HDU 1015 Safecracker(第一次用了搜索去遍历超时,第二次用for循环能够了,思路一样的)

    Safecracker Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total S ...

随机推荐

  1. OSG-基础知识-程序框架

    本文转至http://www.cnblogs.com/shapherd/archive/2010/08/10/osg.html 作者写的比较好,再次收藏,希望更多的人可以看到这个文章 互联网是是一个相 ...

  2. Python :编写条件分支代码的技巧

    『Python 工匠』是什么? 我一直觉得编程某种意义是一门『手艺』,因为优雅而高效的代码,就如同完美的手工艺品一样让人赏心悦目. 在雕琢代码的过程中,有大工程:比如应该用什么架构.哪种设计模式.也有 ...

  3. 创建并运行第一个Django项目

    首先, 添加Django模块: 在CMD命令行输入 python -m django --version 查看Django版本: 创建第一个Django项目: 整个工程的目录结构: mysite目录是 ...

  4. 跟浩哥学自动化测试Selenium -- 浏览器的基本操作与元素定位(3)

    浏览器的基本操作与元素定位 通过上一章学习,我们已经学会了如何设置驱动路径,如何创建浏览器对象,如何打开一个网站,接下来我们要进行一些复杂的操作比如先打开百度首页,在打开博客园,网页后退,前进等等,甚 ...

  5. [USACO09Open] Tower of Hay 干草塔

    为了调整电灯亮度,贝西要用干草包堆出一座塔,然后爬到牛棚顶去把灯泡换掉.干草包会从传送带上运来,共会出现N包干草,第i包干草的宽度是W i ,高度和长度统一为1.干草塔要从底层开始铺建.贝西会选择最先 ...

  6. lintcode12 带最小值操作的栈

    实现一个带有取最小值min方法的栈,min方法将返回当前栈中的最小值. 你实现的栈将支持push,pop 和 min 操作,所有操作要求都在O(1)时间内完成. 建一个栈helpStack,用来存放从 ...

  7. markdown语法介绍

    1. 标题类 每级标题用"# title"表示,共支持6级标题: 2. 段落类 1.建议用换行符控制: 2.用"<p></p>"控制: ...

  8. Bootstrap框架(图标)

    Glyphicons 字体图标 所有可用的图标 包括250多个来自 Glyphicon Halflings 的字体图标.Glyphicons Halflings 一般是收费的,但是他们的作者允许 Bo ...

  9. python leveldb 文档

    标签(空格分隔): python leveldb import leveldb db = leveldb.LevelDB('./db') db.Put('hello', 'world') print ...

  10. POJ 3675 Telescope(简单多边形和圆的面积交)

    Description Updog is watching a plane object with a telescope. The field of vision in the telescope ...