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. AirtestIDE实践二:Poco框架试用

    上一篇用airtest框架做了一个梦幻西游手游的DEMO,这次看看poco的强大之处.首先安装poco:pip install pocoui 其次,把SDK集成到你家游戏中,我这直接用官网提供的一个U ...

  2. 即刻开始使用Kotlin开发Android的12个原因(KAD 30)

    作者:Antonio Leiva 时间:Jul, 11, 2017 原文链接:https://antonioleiva.com/reasons-kotlin-android/ 这组文章已到最后了,它们 ...

  3. MySQL☞自连接

    自连接:一张表中根据自身列之间的关联关系,自己跟自己链接. A.创建一个user表,且插入数据,数据如下: B.分析: 把user表看成两张表,一张员工表,一张领导表,发现员工表中lead(领导编号) ...

  4. docker官网安装

    最近发现一些同学居然不会安装docker,难,不难,只是“网络不好”! 如果是学习的话,目前我发现的比较好的方法还是到清华的开源镜像网站: https://mirror.tuna.tsinghua.e ...

  5. linux命令(实用!)

    本文转载自网络 1.1 shell家族 shell:命令解释器,根据输入的命令执行相应命令. 察看当前系统下有哪些shell: cat /etc/shells 察看当前系统正在使用的shell ech ...

  6. Android开发-API指南-<permission-tree>

    <permission-tree> 英文原文:http://developer.android.com/guide/topics/manifest/permission-tree-elem ...

  7. 【shell 每日一练6】初始化安装Mysql并修改密码

    一.简单实现mysql一键安装 参考:[第二章]MySQL数据库基于Centos7.3-部署 此脚本前提条件是防火墙,selinux都已经设置完毕: [root@web130 ~]# cat Inst ...

  8. Laxcus大数据管理系统2.0(12)- 第十章 运行

    第十章 运行 本章将介绍一些Laxcus集群基本运行.使用情况,结合图片和表格表示.地点是我们的大数据实验室,使用我们的实验集群.数据来自于我们的合作伙伴,软件平台混合了Windows和Fedora  ...

  9. 线性代数之——正交矩阵和 Gram-Schmidt 正交化

    这部分我们有两个目标.一是了解正交性是怎么让 \(\hat x\) .\(p\) .\(P\) 的计算变得简单的,这种情况下,\(A^TA\) 将会是一个对角矩阵.二是学会怎么从原始向量中构建出正交向 ...

  10. Thunder团队第五周 - Scrum会议4

    Scrum会议4 小组名称:Thunder 项目名称:i阅app Scrum Master:李传康 工作照片: 邹双黛同学在拍照,所以不在照片内. 参会成员: 王航:http://www.cnblog ...