神奇的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

  1. a≥x
  2. a 的各个数位不包含除了 47 以外的其他数字。

现在,给定两个整数 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在非搜索题中的应用)的主要内容,如果未能解决你的问题,请参考以下文章

深度优先搜索DFS

dfs整理:

一文搞定搜索!

广度优先(bfs)和深度优先搜索(dfs)的应用实例

基本算法——深度优先搜索(DFS)和广度优先搜索(BFS)

Leetcode之深度优先搜索(DFS)专题-DFS+记忆化 329. 矩阵中的最长递增路径(Longest Increasing Path in a Matrix)