蓝桥杯刷题总结-合集(持续更新)

蓝桥杯刷题总结

待办:

  • 0. 刷题前须知
  • 1. 递归与递推
  • 2. 二分
  • 3. 前缀和
  • 4. 数学
  • 5. 枚举
  • 6. 模拟
  • 7. 排序
  • 8. 双指针
  • 9. BFS
  • 10. 图论
  • 11. 树状数组
  • 12. 线段树
  • 13. 贪心
  • 14. 数论
  • 15. 简单DP
  • 16. 复杂DP
  • 17. 杂题
  • 18. 十一届蓝桥杯真题
  • 19. 十二届蓝桥杯真题

BaseOn : https://www.acwing.com

0、刷提前的须知

1、输入

in.next()in.nextLine()

package com.caopeng.zero;

import java.util.Scanner;

/**
 * @author Crescent_P
 * @date 2021-12-02 19:41
 */
public class InputOutput1 {
   
    public static void main(String[] args) {
   
        // Scanner类输入
        Scanner in = new Scanner(System.in);
        // 整数
//        int a = in.nextInt();
        // 浮点数
//        double v = in.nextDouble();
        // 长整数
//        long c = in.nextLong();
        // short
//        short d = in.nextShort();
        // 字符串
        String s1 = in.next();          // c++ 中的 cin/scanf 遇到空格结束
        String s2 = in.nextLine();      // c++ 中的 gets      遇到回车结束
        // 输入 abc def g
        System.out.println("s1 :" + s1);    // s1 :abc
        System.out.println("s2 :" + s2);    // s2 : def g
    }
}

hasNext()

package com.caopeng.zero;

import java.util.Scanner;

/**
 * @author Crescent_P
 * @date 2021-12-02 19:41
 */
public class InputOutput2 {
   
    public static void main(String[] args) {
   
        // Scanner类输入
        Scanner in = new Scanner(System.in);
        // hasNext()
        // hasNext()返回的是bool类型、当缓冲区有数据返回true
        // 当缓冲区没有数据会发生阻塞、等待数据的输入
        // 遇到多组输入,不知道什么时候能结束输入可以使用
        // while(in.hasNext()) 相当于 while(scanf())
        int a,b,c;
        while(in.hasNext()){
   
            a = in.nextInt();
            b = in.nextInt();
            c = in.nextInt();
            System.out.printf("%d\n",a+b+c);    // 模式化输出
        }

    }
}

image-20211202195320323

2、输出

// 常见的输出
System.out.println();       // 带换行的
System.out.print();         // 不带换行的
System.out.printf();        // 格式化输出,相当于c/c++ 的 printf

3、快速输出输出

BufferedReaderBufferedWriter实现

4、集合容器

1、递归与递推

递归实现指数型枚举

java

import java.util.*;

public class Main{
   
    static Scanner in = new Scanner(System.in);		// 输入
    // 看题目范围 n是1到15,我们稍微把数组开大一点点、防止数组越界。
    static int max = 20,n;							
    // 判断每一位是否被用过
    static boolean[] st = new boolean[max];
    public static void main(String[] args){
   
        n = in.nextInt();
        dfs(0);
    }
    // dfs(深度优先搜索)
    private static void dfs(int u){
   
        // 搜索到最后一位
        if(u == n){
   
            // 打印输出
            for(int i = 0;i < n;i++){
   
                if(st[i]) System.out.printf("%d ",i+1);
            }
            System.out.println();
            return;
        }
        // 要第u位
        st[u] = true;
        dfs(u+1);
        // 不要第u位
        st[u] = false;
        dfs(u+1);
    }
}

C/C++

#include <bits/stdc++.h>

using namespace std;

const int N = 20;

bool st[N];

int n;

void dfs(int u){
    // 递归到了叶子节点
    if(u == n){
        for(int i = 0;i < n;i++){
            if(st[i]) cout << i + 1 << " ";
        }
        cout << endl;   // 换行
        return;
    }
    // 选
    st[u] = true;
    dfs(u+1);
    
    // 不选
    st[u] = false;
    dfs(u+1);
}

int main(){
    cin >> n;
    dfs(0);
    return 0;
}

img

递归实现排列型枚举

Java

import java.util.*;
import java.io.*;
public class Main {
   
    static Scanner in = new Scanner(System.in);
    static int max = 10, n;
    static int[] path = new int[max];       // 存储路径
    static boolean[] st = new boolean[max]; // 记录每个数字是否被使用了
    static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    public static void main(String[] args)throws Exception{
   
        n = in.nextInt();
        dfs(0);
        out.flush();
    }
    private static void dfs(int u) throws Exception{
   
        if(u == n){
   
            for(int i = 0;i < n;i++) out.write(path[i] + " ");	// 快速写出
            out.write("\n");       // 换行
            return;
        }
        for(int i = 0;i < n;i++){
   
            if(!st[i]){
   
                st[i] = true;
                path[u] = i+1;
                dfs(u+1);
                st[i] = false;
                path[u] = 0;
            }
        }
    }
}

C/C++

#include <bits/stdc++.h>

using namespace std;

const int N = 10;

int path[N];
bool st[N];
int n;

void dfs(int u){
    if(u == n){
        for(int i = 0;i < n;i++) cout << path[i] << " ";
        cout << endl;
        return;
    }
    for(int i = 0;i < n;i++){
        if(!st[i]){
            st[i] = true;
            path[u] = i+1;
            dfs(u+1);
            st[i] = false;
        }
    }
}

int main(){
    cin >> n;
    dfs(0);
    return 0;
}

递归实现组合型枚举

Java

import java.util.*;
public class Main{
   
    static Scanner in = new Scanner(System.in);
    static int max = 30,n,m;
    static int[] path = new int[max];
    public static void main(String[] args){
   
        n = in.nextInt();
        m = in.nextInt();
        dfs(0);
        return;
    }
    public static void dfs(int u){
   
        if(u == m){
   
            for(int i = 0;i < m;i++) System.out.printf("%d ",path[i]);
            System.out.println();
            return;
        }
        for(int i = 1;i <= n;i++){
   
            if(u == 0) path[u] = i;
            else {
   
                if(path[u-1] < i) path[u] = i;
                else continue;
            }
            dfs(u+1);
        }
    }
}

C/C++

#include <bits/stdc++.h>

using namespace std;

const int N = 30;

int path[N];

int n,m;

void dfs(int u){
    if(u == m){
        for(int i = 0;i < m;i++) cout << path[i] << " ";
        cout << endl;
        return;
    }
    for(int i = 1;i <= n;i++){
        if(u == 0) path[u] = i;
        else{
            // 前一位要比这一位小
            if(path[u-1] < i) path[u] = i;
            else continue;
        }
        dfs(u+1);
    }
}

int main(){
    cin >> n >> m;
    dfs(0);
    return 0;
}

简单的斐波那契数列

java

import java.util.*;
public class Main{
   
    static Scanner in = new Scanner(System.in);
    static int n,a = 0,b  = 1;
    public static void main(String[] args){
   
        n = in.nextInt();
        for(int i = 0;i < n;i++){
   
            System.out.printf("%d ",a);
            int temp = a + b;
            a = b;
            b = temp;
        }
    }
}

C/C++

#include <bits/stdc++.h>

using namespace std;

// 递推公式
// a[i] = a[i-1] + a[i-2]

int n;

int main(){
    int a = 0,b = 1;
    cin >> n;
    for(int i = 0;i < n;i++){
        cout << a << " ";
        int temp = a + b;
        b = a;
        a = temp;
    }
    cout << endl;
    return 0;
}

费解的开关

想写出这个题目,首先得分析出几个点:

  1. 每个灯泡只能被摁一次,因为摁两次不会有任何改变,并且还多了步数
  2. 摁的顺序是无所谓的,先摁哪个再摁哪个是没关系的。

依靠上面两个结论,我们来看这一题:

  1. 我们可以先只看第一行,第一行我们可以随意摁,但是每个灯泡只能被操作一次。
  2. 第一行被操作过了,轮到第二行,此时第一行如果还有灭的,只能通过第二行来将其熄灭。逻辑就是这样,下面的每一行的灯泡是否操作,都是看上一行灯灯泡的状态。

因此:

  1. 我们枚举第一行的所有状态
    1. 怎么枚举,第一行一共5个灯泡、每个灯泡开或关有两种状态、那么就是2^5=32种状态
  2. 之后根据当前第一行的状态去操作后续的行
  3. 到最后一行、看是否有开的,如果有,说明不能全灭

C/C++

#include <bits/stdc++.h>

using namespace std;

const int N = 6;

char g[N][N],backup[N][N];

// 偏移量,用于遍历(x,y)的上下左右中
int dx[5] = {1,0,-1,0,0},dy[5] = {0,1,0,-1,0};

// 将(x,y)的上下左右摁一遍
void turn(int x,int y){
    for(int i = 0;i < 5;i++){
        int nx = x + dx[i],ny = y + dy[i];
        if(nx < 0 || nx > 5 || ny < 0 || ny > 5) continue;  // 外界不需要考虑
        if(g[nx][ny] == '0') g[nx][ny] = '1';
        else g[nx][ny] = '0';
    }
}

int main(){
    int T;
    cin >> T;
    while(T--){
        // 将图读入
        for(int i = 0;i < 5;i++) cin >> g[i];
        // 第一行一共5个按钮,每个按钮开或不开一共2种情况,2^5 = 32
        int ans = 10;
        for(int op = 0;op < 32;op++){
            memcpy(backup,g,sizeof g);  // 将 g的内容放入backup中备份
            int step = 0;   // 操作的步数
            // 第一行所有情况
            for(int i = 0;i < 5;i++){
                // 当前对应了1就操作
                if(op >> i & 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);
                    }
                }
            }
            // 最后一行是不能有关闭的,否则就是不能实现
            bool dark = false;
            for(int i = 0;i < 5;i++){
                if(g[4][i] == '0'){
                    dark = true;
                    break;
                }
            }
            if(!dark) ans = min(ans,step);
            memcpy(g,backup,sizeof g);  // 将 g的内容放入backup中备份
        }
        if(ans > 6) ans = -1;
        cout << ans << endl;
    }
    return 0;
}

java

import java.util.*;
public class Main{
   
    static Scanner in = new Scanner(System.in);
    static int max = 5;
    static char[][] g = new char[max][max];
    static char[][] backup = new char[max][max];
    static int[] dx = {
   1,0,-1,0,0},dy = {
   0,1,0,-1,0};
    public static void main(String[] args){
   
        int T = in.nextInt();
        // T个测试样例
        while(T-- > 0){
   
            // 读入图
            int res 
  • 14
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值