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. mysql新手入门随笔4

    40.子查询:出现在其他SQL语句里的SELECT语句 例如:SELECT sname,mark FROM student WHERE mark = (SELECT max(mark) FROM st ...

  2. Python列表操作大全(非常全)

    Python列表操作大全(非常全!!!) 对于python列表的理解可以和C语言里面的数组进行比较性的记忆与对照,它们比较相似,对于python里面列表的定义可以直接用方括号里加所包含对象的方法,并且 ...

  3. TPO-14 C1 Locate a political book

    TPO-14 C1 Locate a political book 第 1 段 1.Listen to a conversation between the student and librarian ...

  4. linux学习总结----shell编程

    ## 环境变量 ## 全局变量 ``` 常见的全局环境变量 PATH 指令的搜索路径 HOME 用户的家目录 LOGNAME 登录名 SHELL 脚本的类型 使用全局环境变量 echo $PATH 自 ...

  5. OpenMPI运行问题:enough slots available in the system

    版本: Open MPI 3.0.1 编译好可执行的C语言程序后,使用 mpirun -np 3 Test 命令,发现没有正常运行,而是报错: There are not enough slots a ...

  6. 【Linux 运维】Centos7初始化网络配置

    设置网络 (1)动态获取一个IP地址 #dhclient        系统自动自动获取一个IP地址#ip addr         查看获取的ip地址(2)查看网关,子网掩码 虚拟机编辑>虚拟 ...

  7. 洛谷 P1781 宇宙总统:sort(string)

    题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出格式 输入格式: 第一行为一个整数n,代表竞选 ...

  8. [leetcode-667-Beautiful Arrangement II]

    Given two integers n and k, you need to construct a list which contains n different positive integer ...

  9. Python高级编程-itertoos模块

    Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数. 首先我们看看itertools模块提供的几个“无限”迭代器, import itertools naturals = ...

  10. BluetoothServerSocket详解

    一. BluetoorhServerSocket简介 1. 继承关系 public final class BluetoothServerSocket extends Object implement ...