神奇的dfs(dfs在非搜索题中的应用)
Posted 卷王2048
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了神奇的dfs(dfs在非搜索题中的应用)相关的知识,希望对你有一定的参考价值。
神奇的dfs(dfs在非搜索题中的应用)
1.处理表达式
例题一:1225. 正则问题 - AcWing题库
题目
考虑一种简单的正则表达式:
只由 x ( ) | 组成的正则表达式。
小明想求出这个正则表达式能接受的最长字符串的长度。
例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是: xxxxxx,长度是6。
输入格式
一个由x()|组成的正则表达式。
输出格式
输出所给正则表达式能接受的最长字符串的长度。
数据范围
输入长度不超过100,保证合法。
输入样例:
((xx|xxx)x|(x|xx))xx
输出样例:
6
题解
import java.util.Scanner;
/**
* @see 字符串 深搜 dfs
* https://www.acwing.com/problem/content/1227/
*/
public class Main
static Scanner sc = new Scanner(System.in);
static String ss;
static int u;
static int dfs()
int res = 0;
while (u<ss.length())
if (ss.charAt(u)=='(')
u++;
res+=dfs();
u++;
else if (ss.charAt(u)=='|')
u++;
res = Math.max(res,dfs());
else if (ss.charAt(u)==')')
break;
else
u++;
res++;
return res;
public static void main(String[] args)
ss = sc.next();
// System.out.println(ss);
System.out.println(dfs());
分析思路:
例题二:3483. 2的幂次方 - AcWing题库
每个正数都可以用指数形式表示。
例如,137=27+23+20
让我们用 a(b) 来表示 ab。
那么 137 可以表示为 2(7)+2(3)+2(0)。
因为 7=22+2+20,3=2+20,所以 137 最终可以表示为 2(2(2)+2+2(0))+2(2+2(0))+2(0)。
给定一个正数 n,请你将 n 表示为只包含 0 和 2 的指数形式。
输入格式
输入包含多组数据。
每组数据占一行,一个正数 nn。
输出格式
每组数据输出一行,一个指数形式表示。
数据范围
1≤n≤200001≤n≤20000,
每个输入最多包含 100100 组数据。
输入样例:
1315
输出样例:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
题解
import java.util.Scanner;
/**
* @see 深搜 https://www.acwing.com/problem/content/3486/
*/
public class Main
static final int N = 20010;
static int n;
static String dfs(int n)
StringBuilder res = new StringBuilder();
boolean first = true;
for (int i = 29;i>=0;i--)
if ((n>>i&1)==1)
if (!first)
res.append("+");
else
first = false;
String temp = "";
if (i==0)
res.append("2(0)");
else if (i==1)
res.append("2");
else
temp = "2("+dfs(i)+")";
res.append(temp);
return res.toString();
public static void main(String[] args)
Scanner sc = new Scanner(System.in);
while (sc.hasNext())
n = sc.nextInt();
System.out.println(dfs(n));
分析思路
例题三:3284. 化学方程式 - AcWing题库
2.处理相同但规模变化的任务
例题一:459. 螺旋矩阵 - AcWing题库
题目
一个 n 行 n 列的螺旋矩阵可由如下方法生成:
从矩阵的左上角(第 1 行第 1 列)出发,初始时向右移动;如果前方是未曾经过的格子,则继续前进,否则右转;重复上述操作直至经过矩阵中所有格子。
根据经过顺序,在格子中依次填入 1,2,3,…,n2,便构成了一个螺旋矩阵。
下图是一个 n=4 时的螺旋矩阵。
现给出矩阵大小 n 以及 i 和 j,请你求出该矩阵中第 i 行第 j 列的数是多少。
输入格式
输入共一行,包含三个整数 n,i,j每两个整数之间用一个空格隔开,分别表示矩阵大小、待求的数所在的行号和列号。
输出格式
输出共一行,包含一个整数,表示相应矩阵中第 ii 行第 jj 列的数。
数据范围
1≤n≤30000
1≤i,j≤n
输入样例:
4 2 3
输出样例:
14
3.枚举满足一定条件的所有情况
例题1.17. 电话号码的字母组合 - 力扣
题目
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = ""
输出:[]
示例 3:
输入:digits = "2"
输出:["a","b","c"]
提示:
0 <= digits.length <= 4
digits[i]
是范围['2', '9']
的一个数字。
题解
import java.util.ArrayList;
import java.util.List;
/**
* @see 深搜 dfs 列出所有满足一定条件的情况
* https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/
*/
public class LetterCombinations
List<String> res = new ArrayList<>();
String[] ss = "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz";
void dfs(int u, String digits, String path)
if (u == digits.length())
res.add(path);
else
for (int i = 0; i < ss[digits.charAt(u) - '0'].length(); i++)
dfs(u + 1, digits, path + ss[digits.charAt(u) - '0'].charAt(i));
public List<String> letterCombinations(String digits)
if ("".equals(digits))
return res;
dfs(0, digits, "");
return res;
public static void main(String[] args)
String input = "23333";
System.out.println(new LetterCombinations().letterCombinations(input));
问题分析
传参:
1.遍历输入字符串的指针
2.原字符串本身
3.每一种选择的路径
例题2:输出0-10^9
之间所有各个位上只有4或7,的数
题目
用 f(x)
来表示满足下列条件的最小正整数 a
:
a≥x
。a
的各个数位不包含除了4
和7
以外的其他数字。
现在,给定两个整数 l,r(l≤r),
请你计算 f(l)+f(l+1)+…+f(r)
的值。
输入格式
一行,两个整数 l,r
输出格式
一行,一个整数表示求得的和。
数据范围
前三个测试点满足 1≤l≤r≤10
所有测试点满足1≤l≤r≤109
。
输入样例1:
2 7
输出样例1:
33
输入样例2:
7 7
输出样例2:
7
题解
方法一:dfs
static ArrayList<Long> list = new ArrayList<>();
static void dfs(int u,long x)
list.add(x);
if (u==10)
return;
dfs(u+1,10*x+4);
dfs(u+1,10*x+7);
dfs(0,0);
Collections.sort(list);
方法二:进位制枚举
for(int i=1;i<1<<10;i++)
LL num1=0,num2=0,k=1,t=i;
while(t)
if(t%2==0) num1+=4*k,num2+=7*k;
else num1+=7*k,num2+=4*k;
k*=10,t/=2;
s[cnt++]=num1;
s[cnt++]=num2;
完整题解
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
/**
* @see https://www.acwing.com/problem/content/3737/
*/
public class Main
static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static int nextInt() throws Exception
in.nextToken();
return (int)in.nval;
static String next()throws Exception
in.nextToken();
return in.sval;
static long l,r;
static final int INF = (int)10e9;
static ArrayList<Long> list = new ArrayList<>();
static void dfs(int u,long x)
list.add(x);
if (u==10)
return;
dfs(u+1,10*x+4);
dfs(u+1,10*x+7);
public static void main(String[] args)throws Exception
l = nextInt();
r = nextInt();
dfs(0,0);
Collections.sort(list);
long res = 0;
int n = list.size();
for(int i = 1; i <n; i++)
long a = list.get(i-1)+1,b = list.get(i);
res+=list.get(i)*Math.max(0,(Math.min(r,b)-Math.max(l,a)+1));
out.println(res);
out.flush();
x+4);
dfs(u+1,10*x+7);
public static void main(String[] args)throws Exception
l = nextInt();
r = nextInt();
dfs(0,0);
Collections.sort(list);
long res = 0;
int n = list.size();
for(int i = 1; i <n; i++)
long a = list.get(i-1)+1,b = list.get(i);
res+=list.get(i)*Math.max(0,(Math.min(r,b)-Math.max(l,a)+1));
out.println(res);
out.flush();
以上是关于神奇的dfs(dfs在非搜索题中的应用)的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode之深度优先搜索(DFS)专题-DFS+记忆化 329. 矩阵中的最长递增路径(Longest Increasing Path in a Matrix)