AcWing蓝桥杯辅导课:第一讲递推与递归

news2025/7/30 7:59:45

AcWing 92. 递归实现指数型枚举

在这里插入图片描述
思路:

方法一: 暴力枚举

用二进制加位运算枚举每一个状态,输出即可,时间复杂度为 O ( N 2 N ) O(N2^N) O(N2N)

代码:

import java.util.Scanner;

/**
 * @Description
 * @Author: PrinceHan
 * @CreateTime: 2023/2/22 11:08
 */
public class Main {
    static Scanner scanner = new Scanner(System.in);
    static int n;

    public static void main(String[] args) {
        n = scanner.nextInt();
        for (int i = 0; i < (1 << n); i++) {
            for (int j = 0; j < n; j++) {
                if (((i >> j) & 1) == 1) {
                    System.out.print((j + 1) + " ");
                }
            }
            System.out.println();
        }
    }

}

方法二: 深搜

用一个数组存储每个数字的状态, 0表示不放, 1表示放,如果当前状态是1的话,就输出该数,与求全排列代码类似。

import java.util.Scanner;

/**
 * @Description
 * @Author: PrinceHan
 * @CreateTime: 2023/2/22 11:08
 */
public class Main {
    static Scanner scanner = new Scanner(System.in);
    static final int N = 20;
    static int n;
    // 0不选 1选
    static int[] st = new int[N];

    public static void main(String[] args) {
        n = scanner.nextInt();
        dfs(1);
    }

    public static void dfs(int u) {
        if (u == n + 1) {
            for (int i = 1; i <= n; i++) {
                if (st[i] == 1) System.out.print(i + " ");
            }
            System.out.println();
            return;
        }

        st[u] = 0;
        dfs(u + 1);
        st[u] = 1;
        dfs(u + 1);
    }

}

AcWing 94. 递归实现排列型枚举

在这里插入图片描述
思路:
深度优先搜索,时间复杂度为 O ( N ∗ N ! ) O(N*N!) O(NN!),注意Java 的 System.out.println() 输出效率低, 本题会超时,所以用 BufferedWrite 来输出。

代码:

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Scanner;

/**
 * @Description
 * @Author: PrinceHan
 * @CreateTime: 2023/2/22 10:25
 */
public class Main {
    static final int N = 15;
    static int n;
    static boolean[] st = new boolean[N];
    static int[] a = new int[N];
    static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        dfs(0);
        out.flush();
    }

    public static void dfs(int step) throws IOException {
        if (step == n) {
            for (int i = 0; i < n; i++)
                out.write(a[i] + " ");
            out.write('\n');
        } else {
            for (int i = 1; i <= n; i++) {
                if (!st[i]) {
                    a[step] = i;
                    st[i] = true;
                    dfs(step + 1);
                    st[i] = false;
                }
            }
        }
    }
}

AcWing 717. 简单斐波那契

在这里插入图片描述
代码:

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Scanner;

/**
 * @Description
 * @Author: PrinceHan
 * @CreateTime: 2023/2/22 10:43
 */
public class Main {
    static Scanner scanner = new Scanner(System.in);
    static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    static final int N = 50;
    static int[] fi = new int[N];
    static int n;

    public static void main(String[] args) throws IOException {
        n = scanner.nextInt();
        fi[1] = 0;
        fi[2] = 1;
        for (int i = 3; i <= n; i++) {
            fi[i] = fi[i - 1] + fi[i - 2];
        }
        for (int i = 1; i <= n; i++) {
            out.write(fi[i] + " ");
        }
        out.flush();
    }
}

AcWing 95. 费解的开关

在这里插入图片描述

思路:

考虑第一行,有 2 n 2 ^ n 2n 种不同的状态。对于第一行的每个灯的状态,由于每个开关状态的改变会影响上下左右的所有开关的状态,所以在第一行,如果某灯是灭的话,有且仅有该灯下面第二行的开关的改变能影响该灯的状态,也就是说,只有正下方的开关可以改变上一层的状态,第 n n n 行 确定 n + 1 n + 1 n+1 行的状态,第一行确定整个的状态,所以只需要用二进制枚举第一行的状态即可,判断最后一行是否都为亮的,如果都是亮的,则有可行解,再判断可行解与 6 的 关系。

为保证不同的操作方式之间的结果不干扰,一开始要对原始数组先备份,然后再还原。

代码:

import java.util.Arrays;
import java.util.Scanner;

/**
 * @Description
 * @Author: PrinceHan
 * @CreateTime: 2023/2/23 15:46
 */
public class Main {

    static final int N = 6;
    static char[][] g = new char[N][N], backup = new char[N][N];
    static int n;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();

        while (n-- != 0) {

            for (int i = 0; i < 5; i++) {
                String s = scanner.next();
                g[i] = s.toCharArray();
            }

            int res = 10;


            for (int op = 0; op < (1 << 5); op++) {

                for (int j = 0; j < 5; j++) {
                    backup[j] = Arrays.copyOf(g[j], 5);
                }

                int step = 0;

                for (int i = 0; i < 5; i++) {
                    if ((op >> i & 1) == 1) {
                        step++;
                        turn(0, i);
                    }
                }

                for (int i = 0; i < 4; i++) {
                    for (int j = 0; j < 5; j++) {
                        if (g[i][j] == '0') {
                            step++;
                            turn(i + 1, j);
                        }
                    }
                }
                boolean flag = false;

                for (int i = 0; i < 5; i++) {
                    if (g[4][i] == '0') {
                        flag = true;
                        break;
                    }
                }

                if (!flag) res = Math.min(res, step);
                for (int j = 0; j < 5; j++) {
                    g[j] = Arrays.copyOf(backup[j], 5);
                }

            }

            if (res > 6) System.out.println(-1);
            else System.out.println(res);
        }

    }


    public static void turn(int x, int y) {
        int[] dx = {-1, 1, 0, 0, 0}, dy = {0, 0, -1, 1, 0};

        for (int i = 0; i < 5; i++) {
            int a = x + dx[i], b = y + dy[i];
            if (a < 0 || a >= 5 || b < 0 || b >= 5) continue;
            g[a][b] ^= 1;
        }
    }
}

AcWing 93. 递归实现组合型枚举

在这里插入图片描述
思路:

搜索一个数,然后搜索下一个比该数大的数。

剪枝条件: 设当前搜索的是 第 u u u 个数,则已经有了 u − 1 u - 1 u1 个数,搜索到了 s t a r t start start ,一共有 n n n 个数,还剩 n − s t a r t + 1 n - start + 1 nstart+1 个数。

如果 u − 1 + n − s t a r t + 1 < m u - 1 + n - start + 1 \lt m u1+nstart+1<m,凑不齐 m m m 个数的组合,就剪去该分支。

代码:

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Scanner;

/**
 * @Description
 * @Author: PrinceHan
 * @CreateTime: 2023/2/22 14:38
 */
public class Main {
    static final int N = 30;
    static int n, m;
    static int[] a = new int[N];
    static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();

        dfs(1, 1);
        out.flush();
    }

    public static void dfs(int step, int start) throws IOException {
        if (step + n - start < m) return;
        if (step == m + 1) {
            for (int i = 1; i <= m; i++)
                out.write(a[i] + " ");
            out.write('\n');
        } else {
            for (int i = start; i <= n; i++) {
                a[step] = i;
                dfs(step + 1, i + 1);
            }
        }
    }
}

AcWing 1209. 带分数

在这里插入图片描述
思路:

方法一: 暴力枚举全排列,枚举 a a a, b b b , c c c。枚举 a a a, b b b , c c c过程中配以剪枝, a a a的位数不超过6位。

代码:

import java.util.Scanner;

/**
 * @Description
 * @Author: PrinceHan
 * @CreateTime: 2023/2/23 10:08
 */
public class Main {
    static final int N = 15;
    static int ans;
    static int n;
    static int[] arr = new int[N];
    static boolean[] st = new boolean[N];
    static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        dfs(1);
        System.out.println(ans);
    }

    public static int cal(int a, int b) {
        int sum = 0;

        for (int i = a; i <= b; i++) sum = sum * 10 + arr[i];

        return sum;
    }

    public static void dfs(int u) {
        if (u > 9) {
        // 枚举a, b, c
            for (int i = 1; i <= 6; i++) {
                for (int j = i + 1; j <= 8; j++) {
                    int a = cal(1, i);
                    int b = cal(i + 1, j);
                    int c = cal(j + 1, 9);
                    if (a * c + b == n * c) ans++;
                }
            }

            return;
        }
        for (int i = 1; i <= 9; i++) {
            if (!st[i]) {
                arr[u] = i;
                st[i] = true;
                dfs(u + 1);
                st[i] = false;
            }
        }
    }
}

方法二: 枚举 a a a, c c c。计算 b b b ,判断该组合是否不重不漏用完 1 ∼ 9 1\sim 9 19 中的所有数。

代码:

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.Scanner;

/**
 * @Description
 * @Author: PrinceHan
 * @CreateTime: 2023/2/23 14:27
 */
public class Main {

    static final int N = 15;
    static boolean[] st = new boolean[N], backup = new boolean[N];
    static int n, ans;

    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        dfs_a(0, 0);
        System.out.println(ans);
    }

    public static void dfs_a(int u, int a) {
    	// 如果 a >= n 不满足条件 剪枝
        if (a >= n) return;
        // 在 a的基础上枚举c
        if (a != 0) dfs_c(u, a, 0);

        for (int i = 1; i <= 9; i++) {
            if (!st[i]) {
                st[i] = true;
                dfs_a(u + 1, a * 10 + i);
                st[i] = false;
            }
        }
    }

    public static void dfs_c(int u, int a, int c) {
        if (u > 9) return;
        if (check(a, c)) ans++;
        for (int i = 1; i <= 9; i++) {
            if (!st[i]) {
                st[i] = true;
                dfs_c(u + 1, a, c * 10 + i);
                st[i] = false;
            }
        }
    }

    public static boolean check(int a, int c) {
    	// 防止爆 int
        long b = n * (long) c - (long)a * c;
        if (a * b * c == 0) return false;
        for (int i = 1; i <= 9; i++) {
            backup[i] = st[i];
        }

        while (b != 0) {
            long x = b % 10;
            b /= 10;
            // 出现了0 或者b的数字与 a c 的有重复 不满足条件
            if (x == 0 || backup[(int)x]) return false;
            backup[(int)x] = true;
        }

		// 保证每个数字都用过了
        for (int i = 1; i <= 9; i++) {
            if (!backup[i]) return false;
        }

        return true;
    }
}

AcWing 116. 飞行员兄弟

在这里插入图片描述
思路:

因为本题规模不大,所以可以通过枚举和位运算来求解,一共有 16 个位置,则有 2 16 = 65536 2^{16} = 65536 216=65536 种状态,最后判断开关的状态。用ArrayList 来存储操作,仅当操作数更少的时候,才更新操作集。

代码:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

/**
 * @Description
 * @Author: PrinceHan
 * @CreateTime: 2023/2/23 16:48
 */
public class Main {
    static final int N = 5;
    static char[][] g = new char[N][N], backup = new char[N][N];

    static class Node {
        int x, y;

        Node(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        ArrayList<Node> ans = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            String s = scanner.next();
            g[i] = s.toCharArray();
        }

        for (int op = 0; op < (1 << 16); op++) {

            for (int j = 0; j < 4; j++) {
                backup[j] = Arrays.copyOf(g[j], g[j].length);
            }

            ArrayList<Node> tmp = new ArrayList<>();


            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if (((op >> (i * 4 + j)) & 1) == 1) {
                        turn(i, j);
                        tmp.add(new Node(i, j));
                    }
                }
            }

            boolean flag = false;
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if (g[i][j] == '+') {
                        flag = true;
                        break;
                    }
                }
            }

            if (!flag) {
                if (ans.isEmpty() || ans.size() > tmp.size()) ans = tmp;
            }

            for (int j = 0; j < 4; j++) {
                g[j] = Arrays.copyOf(backup[j], backup[j].length);
            }

        }

        System.out.println(ans.size());
        for (Node tmp : ans) {
            System.out.println((tmp.x + 1) + " " + (tmp.y + 1));
        }

    }

    public static void turn(int x, int y) {
        for (int i = 0; i < 4; i++) {
            g[x][i] = g[x][i] == '+' ? '-' : '+';
            g[i][y] = g[i][y] == '+' ? '-' : '+';
        }
        g[x][y] = g[x][y] == '+' ? '-' : '+';

    }
}

AcWing 1208. 翻硬币

在这里插入图片描述
思路:

本题有不超过100个元素,枚举状态会超时,可以考虑贪心来做,如果两个字符串某个相同位置的元素不相同,就翻转,操作的次数就加一。这样只需要用到 O ( N ) O(N) O(N) 的时间复杂度。

代码:

import java.util.Scanner;

/**
 * @Description
 * @Author: PrinceHan
 * @CreateTime: 2023/2/24 9:54
 */
public class Main {
    static final int N = 105;
    static char[] s1 = new char[N], s2 = new char[N];
    static String start, end;
    static int n, ans;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        start = scanner.next();
        end = scanner.next();
        n = start.length();
        s1 = start.toCharArray();
        s2 = end.toCharArray();

        for (int i = 0; i < n - 1; i++) {
            if (s1[i] != s2[i]) {
                ans++;
                turn(i);
            }
        }

        System.out.println(ans);

    }

    public static void turn(int u) {
        s1[u] = s1[u] == '*' ? 'o' : '*';
        s1[u + 1] = s1[u + 1] == '*' ? 'o' : '*';
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/367844.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何让WinForms应用程序拥有Windows 11设计主题?

Telerik UI for WinForms拥有适用Windows Forms的110多个令人惊叹的UI控件。所有的UI for WinForms控件都具有完整的主题支持&#xff0c;可以轻松地帮助开发人员在桌面和平板电脑应用程序提供一致美观的下一代用户体验。Windows 11主题的时代已经到来了&#xff0c;可以为WinF…

Vue+Spring Boot前后端开发手册,开源获赞68K

企业技能要求 现在企业通常要求程序员既要有实战技能&#xff0c;也要内功扎实&#xff0c;对于新项目可以快速上手&#xff0c;熟悉底层原理后还应后劲十足&#xff0c;因此在笔试和面试时结合底层知识、实战应用、设计思维三方面进行考查。针对这3个方面的需求&#xff0c;阿…

【Java】用记事本实现“HelloWorld”输出

【在进行以下操作前需要下载好JDK并配置好对应的环境变量】 一、在任意文件夹中创建一个新的文本文档文件并写入以下代码 public class Hello{public static void main (String[] args){System.out.print("Hello,World!");} } 二、修改文件名称及文件类型为 Hello.j…

Python3,为了无损压缩gif动图,我不得不写了一个压缩神器,真香。

gif动图无损压缩1、引言2、代码实战2.1 模块介绍2.2 安装2.3 代码示例3、总结1、引言 小屌丝&#xff1a;鱼哥&#xff0c; 求助~ 求助~ 求助~ 小鱼&#xff1a;你这是告诉我&#xff0c;重要的事情 说三遍吗&#xff1f; 小屌丝&#xff1a;你可以这么理解。 小鱼&#xff1a…

程序员35岁以后就没有出路了吗?听听京东10年测开的分析

国内的互联网行业发展较快&#xff0c;所以造成了技术研发类员工工作强度比较大&#xff0c;同时技术的快速更新又需要员工不断的学习新的技术。因此淘汰率也比较高&#xff0c;超过35岁的基层研发类员工&#xff0c;往往因为家庭原因、身体原因&#xff0c;比较难以跟得上工作…

RocketMQ 延迟队列

什么是延迟队列指消息发送到某个队列后&#xff0c;在指定多长时间之后才能被消费。应用场景RocketMQ 延迟队列定时消息&#xff08;延迟队列&#xff09;是指消息发送到broker后&#xff0c;不会立即被消费&#xff0c;等待特定时间投递给真正的topic。broker有配置项messageD…

自学黑客2年都没入门,从零入门渗透有那么难吗?附入门教程。

最近年底了&#xff0c;不少朋友都是在总结一年的学习成果。最后不少人发现完成情况与自己最初定下的目标相去甚远。 我认识不少人自学大半年了&#xff1a;b站&#xff0c;网盘&#xff0c;各种各样的资源数不胜数&#xff0c;总之只要是跟安全相关的不管学不学&#xff0c;先…

IP地址,子网掩码,网段 概念详解

文章目录1. 子网掩码1.1 子网掩码的概念及作用1.2 子网掩码的组成1.3 子网掩码的表示方法1.4 为什么要使用子网掩码&#xff1f;1.5 子网掩码的分类2. 子网掩码和IP地址的关系2.1 根据掩码确定网段IP地址是以 网络号和 主机号来标示网络上的主机的&#xff0c;我们把网络号相同…

「JVM 编译优化」Graal 编译器

文章目录1. 历史背景2. 构建编译调试环境3. JVMCI 编译器接口4. 代码中间表示5. 代码优化与生成1. 历史背景 Graal 编译器在 JDK 9 以 Jaotc 提前编译工具的形式首次加入到官方的 JDK 中&#xff0c;JDK 10 开始提供替换&#xff08;得益于 HotSpot 编译器接口&#xff0c;Jav…

vue中的key值

1. 什么是key&#xff1f; 当我们对一个数据进行遍历生成DOM时&#xff0c;vue的内部会根据索引号对其进行key的定义&#xff0c;而key会作为每一个新生成DOM的唯一标识。 2.为什么不建议索引值作为key&#xff1f; 很多人喜欢直接使用索引值作为key&#xff0c;当所遍历的数…

项目缓存问题处理

1、public/index.html文件头部配置 <meta http-equiv"pragram" content"no-cache"> <meta http-equiv"cache-control" content"no-cache,no-store,must-revalidate"> <meta http-equiv"expires" content&…

Video 标签无法播放 mp4 的原因和解决办法

问题 用 QQ 的截图录屏功能录制的 mp4 视频&#xff0c;无法用 <video> 标签正常播放。 原因 通过搜索的说法是&#xff1a; 查阅文档&#xff08;不知道是啥文档&#xff09;&#xff0c;关于video标签所支持的视频格式和编码&#xff1a; MPEG4 带有H.264视频编码和…

【Windows Server 2019】发布服务器 | 远程桌面服务的安装与配置 Ⅰ——理论,实验拓扑和安装基于RemoteAPP的RDS

目录1. 理论1.1 什么是远程桌面服务2. 实验拓扑2.1 拓扑说明3. 安装基于RemoteAPP的RDS关联博文1. 理论 1.1 什么是远程桌面服务 远程桌面服务 (RDS) 是一个卓越的平台&#xff0c;可以生成虚拟化解决方案来满足每个最终客户的需求&#xff0c;包括交付独立的虚拟化应用程序、…

茂名市 2021 年高中信息技术学科素养展评

没事干&#xff0c;发一下去年去比赛的题目。 目录 第一题 30分 第二题 30分 第一题 30分 题目&#xff1a; “姐姐&#xff0c;乘除法运算太难了&#xff0c;有什么办法能熟练掌握吗&#xff1f;”今年 读小学四年级的表弟向李红求救。为了提高表弟的运算能力&#xff0c;…

Candence allegro 创建等长的方法

随着源同步时序电路的发展,越来越多的并行总线开始采用这种时序控制电路,最典型的代表当属目前炙手可热的DDRx系列。下图这种点到点结构的同步信号,对于攻城狮来说,设置等长约束就非常easy了图片。 But,对于有4、6、8、、、等多颗DDR芯片的ACC同步信号来说,要设置等长约束…

在Excel中按条件筛选数据并存入新的表

案例 老板想要看去年每月领料数量大于1000的数据。手动筛选并复制粘贴出来,需要重复操作12次,实在太麻烦了,还是让Python来做吧。磨刀不误砍柴工,先整理一下思路: 1读取原表,将数量大于1000的数据所对应的行整行提取(如同在excel表中按数字筛选大于1000的) 2将提取的数…

Mysql安装和基本使用

MySQLMySQL 是一个关系型数据库管理系统&#xff0c;由瑞典 MySQL AB 公司开发&#xff0c;目前属于 Oracle 公司。MySQL 是一种关联数据库管理系统&#xff0c;关联数据库将数据保存在不同的表中&#xff0c;而不是将所有数据放在一个大仓库内&#xff0c;这样就增加了速度并提…

Linux 驱动基础

注册驱动模块时给模块传递参数 在一些情况下&#xff0c;我们要动态的改变驱动中某个变量的值&#xff0c;那么就可以在注册时给驱动模块传递参数。 给驱动模块中传递参数&#xff0c;需要定义好接受参数值的全局变量&#xff0c;并调用module_param 来引用它&#xff0c;具体…

Spring架构篇--2.6 远程通信基础--Rpc-Socket实战篇

前言&#xff1a;微服务之间怎么通过socket完成通信&#xff1b;本文通过demo 展示微服务如何通过socket 完成服务之间的通信&#xff1b; 1 使用maven新建两个springboot 服务&#xff1a;模拟实现订单通过订单号获取商品信息&#xff1a; 1.1 创建建springboot 项目后&…

1080T、2080T、4070T显卡的深度学习性能测试和结论

先说结论&#xff1a; 4070T显卡FP32的训练和推理速度跟3090应该基本类似。但由于显存12G偏低&#xff0c;4070T不太适合如今的深度学习模型训练&#xff08;新手列外&#xff0c;大部分模型都能训练起来&#xff0c;耗电也相对很低&#xff09;&#xff0c;更适合测试最新的一…