HDOJ(HDU).1015 Safecracker (DFS)
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)的更多相关文章
- HDOJ/HDU 1015 Safecracker(深搜)
Problem Description === Op tech briefing, 2002/11/02 06:42 CST === "The item is locked in a Kle ...
- HDOJ/HDU 1015 Safecracker(枚举、暴力)
Problem Description === Op tech briefing, 2002/11/02 06:42 CST === "The item is locked in a Kle ...
- hdu 1015 Safecracker 水题一枚
题目链接:HDU - 1015 === Op tech briefing, 2002/11/02 06:42 CST === "The item is locked in a Klein s ...
- HDU 1015 Safecracker【数值型DFS】
Safecracker Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- HDU 1015 Safecracker (DFS)
题意:给一个数字n(n<=12000000)和一个字符串s(s<=17),字符串的全是有大写字母组成,字母的大小按照字母表的顺序,比如(A=1,B=2,......Z=26),从该字符串中 ...
- hdu 1015(DFS)
Safecracker Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- HDU 1015 Safecracker
解题思路:这题相当诡异,样例没过,交了,A了,呵呵,因为理论上是可以通过的,所以 我交了一发,然后就神奇的过了.首先要看懂题目. #include<cstdio> #include< ...
- ZOJ 1403&&HDU 1015 Safecracker【暴力】
Safecracker Time Limit: 2 Seconds Memory Limit: 65536 KB === Op tech briefing, 2002/11/02 06:42 ...
- HDU 1015 Safecracker(第一次用了搜索去遍历超时,第二次用for循环能够了,思路一样的)
Safecracker Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total S ...
随机推荐
- 「日常训练」 Longest Run on a Snowboard (UVA-10285)
题意 其实就是一条二维的LIS,但是还是做的一愣一愣的,多努力. 考虑$dp[i][j]$为从(i,j)出发的二维LIS的最大值,那么$dp[i][j]=max\{dp[i−di[k]][j−dj[k ...
- Django模型与创建管理员用户
默认情况下, 配置使用SQLite:
- 进度条加载与案例优化对比——python使用perf_count方法实现
本章我们将讨论python3 perf_counter()的用法及它的实际应用我从中选取两个python基于rquests库的爬虫实例代码源文件进行举例 Python3 perf_counter() ...
- Centos/Linux 下升级python2.7至3.5.0
(一) 安装Python3.5 (1)在安装python之前,因为linux系统下默认没有安装wget,gcc,首先安装wget,gcc: [root@node6 python_scripts]# y ...
- codeforces 301D Yaroslav and Divisors(树状数组)
Yaroslav has an array p = p1, p2, ..., pn (1 ≤ pi ≤ n), consisting of n distinct integers. Also, he ...
- js经典试题之数组与函数
js经典试题之数组与函数 1:列举js的全局函数? 答案:JavaScript 中包含以下 7 个全局函数escape( ).eval( ).isFinite( ).isNaN( ).parseFlo ...
- Python 再谈字符串
字符串除了要用引号来创建之外,其他和元组一样,不能修改,如果要修改只能用切片或者拼接的方式. 其他的什么乱七八糟的运算符都一样 一些不同 capitalize()-将字符串的第一个字母大写 str1. ...
- 九度oj 题目1495:关键点
题目描述: 在一个无权图中,两个节点间的最短距离可以看成从一个节点出发到达另一个节点至少需要经过的边的个数. 同时,任意两个节点间的最短路径可能有多条,使得从一个节点出发可以有多条最短路径可以选择,并 ...
- ArrayList遍历(JAVA)
假如有个ArrayList变量如下: ArrayList<String> list = new ArrayList<String>(); list.add("arra ...
- php mongodb扩展 其他扩展也类似
MongoDBPHP 扩展 本教程将向大家介绍如何在Linux.window.Mac平台上安装MongoDB扩展. Linux上安装 MongoDB PHP扩展 在终端上安装 你可以在linux中执行 ...