《备战蓝桥》之递推(Java)

简介: 本篇文章针对《备战蓝桥》的另一个题型展开讲解,递推,其实也就是利用循环来完成递归的效果,递归是大化小,而递推就是计算出每个小的,最后去算出大的,下边我们就来针对几道典型例题来一起感受递推。

1.简单斐波那契


原题链接

题解思路:

因为斐波那契数列从第三项开始,每一项都是前两项的和,所以利用循环,并设置变量后移,得出后边的项并打印。


代码实现:


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


2.开关问题总结


下边这些题目都属于开关问题模型,它们都有以下特性:


  • 每个灯泡只能按一次
  • 每个灯泡最后的状态是由能影响其状态的灯泡被按次数的奇偶性决定的,所以顺序无关紧要


2.1费解的开关


原题链接

题解思路:

这道题我们也是通过枚举所有按法,然后找出步数最少的按法,得出最后结果。


题目分析:

1.灯的暗亮情况只与其上下左右的灯被按的次数的奇偶性决定,与

因为要求步数最少,所以一个灯最多只按一次,按两次相当于没按。

2.通过循环枚举第一行所有按与不按的情况,所以按完以后如果第一行的灯灭着,只能通过这个位置的下一行的灯使其变亮(本行因为枚举过所有情况了,所以本行不能再按)。

3.由2.得从第二行开始,每行按与不按的情况都由上一行来决定。

4.当按完最后一行的灯以后(其实已经保证了前四行的灯全亮着),如果第五行还有灯未亮,则无法完成任务。

细节处理:

1.第一行每个灯按与不按的情况共2^5-1种,可以通过二进制数字来表示每个位置的灯的亮与否。

2.按下开关后,所按灯位置的上下左右都需要改变,可以设置偏移量数组完成相应位置的异或1操作,就可以把0变为1,1变成0。


代码实现:


import java.util.*;
public class Main {
    final static int N=5;
    static int[][]g=new int[N][N];
    static int[][]backup=new int[N][N];
    static int[]dx={0,0,0,1,-1};
    static int[]dy={0,1,-1,0,0};
    public static void turn(int x,int y) {
        for (int i = 0; i < 5; i++) {
            int a=x+dx[i];
            int b=y+dy[i];
            if(a<0||a>4||b<0||b>4)continue;
            g[a][b]^=1;
            //异或1完成1变0,0变1的操作
        }
    }
    public static int end() {
        int r=Integer.MAX_VALUE;
        for (int op = 0; op < 32; op++) {
            int step=0;
            for (int i = 0; i < 5; i++) {
            //右移k位与1判断是否是1
                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 dark=true;
            for (int i = 0; i < 5; i++) {
                if(g[4][i]==0) {
                    dark=false;
                    break;
                }
            }
            if(dark)
            r=Math.min(r,step);//记录最小步数
            for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 5; j++) {
                    g[i][j]=backup[i][j];
                }
            }
        }
        if(r>6)return -1;
        return r;
    }
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        int n=scanner.nextInt();
        //n组测试数据
        while (n-->0) {
        //每行输入一个字符串,通过charAt()操作,完成对二维数组的填充
            for (int i = 0; i < 5; i++) {
                String s=scanner.next();
                for (int j = 0; j < 5; j++) {
                    g[i][j]=s.charAt(j)-'0';
                }
            }
            /*数组拷贝,因为接下来会枚举所有情况并在棋盘上进行改动,
      为了保证每种情况的初始状态都是一样的,所以需要提前备份数组*/
            for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 5; j++) {
                    backup[i][j]=g[i][j];
                }
            }
            System.out.println(end());
        }
    }
}

2.2翻硬币


原题链接

题解思路:

这道题其实是上边第二题费解的开关的一道简单版,我们可以将其想为灯泡,设置n-1个开关,每个开关控制两个灯的亮暗。

从第一个开始比较,不同就按开关,遍历整个数组,因为在同一个位置按两次相当于没有按,所以题解唯一。


微信图片_20230110194303.png

代码实现:


import java.util.*;
public class Main {
    final static int N=110;
    static char[]start=new char[N];
    static char[]end=new char[N];
    public static void turn(int i) {
        if(start[i]=='*')
            start[i]='o';
        else
            start[i]='*';
    }
    public static void main(String[]args) {
        Scanner sca=new Scanner(System.in);
        start=sca.next().toCharArray();
        end=sca.next().toCharArray();
        int a=0;
        for(int i=0;i<start.length-1;i++) {
        //因为题目规定一定有解,所以在遍历到倒数第二个硬币的时候,
        //完成最后一步操作,最后一个硬币一定状态相同。
            if(start[i]!=end[i]) {
                turn(i);
                turn(i+1);
                a++;
            }
        }
        System.out.println(a);
    }
}

2.3飞行员兄弟


原题链接

题解思路:

将开关转换为灯泡亮暗问题,最后让开关(灯泡)全处于打开状态即可。

这道题我们乍一看和2.1很像,但我们仔细观察题目可以发现,如果我们用和2.1相同的方法来做,我们会发现不能完成该题,因为2.1我们在对第一行操作进行枚举后,影响第一行灯暗亮状态的只有第二行灯,也就是后边的操作是唯一的,而这道题则不同,影响到一个灯的暗亮状态的有它同行同列的所有灯,所以不能通过相同的方法来解决该题。

但我们可以发现,这道题一共就16个灯泡,我们可以暴力枚举每个灯泡的暗亮状态共2^6种,然后对每种状态进行判断即可。


题解步骤:


1.枚举所有方案

2.按照该方案对灯泡进行操作

3.判断是否全亮,如果全亮记录方案


细节:


1.步数最小:

完成操作后进行判断,如果全亮则比较步数多少,完成实时替换即可.

2.字典序:

在枚举时通过从小到大枚举即可按字典序输出。

3.题解步骤中第二步的操作:


微信图片_20230110194422.png

将 i j 利用4*i+j转换为对应数字,使得所枚举出的方案能右移n位进行操作。


代码实现:


import java.util.*;
import java.io.*;
public class Main {
    static final int N=4;
    static char[][]g=new char[N][N];
    static char[][]backup=new char[N][N];
    static List<PII>res=new ArrayList<PII>();
    static BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
    public static int get(int x,int y) {
        return 4*x+y;
    }
    public static void turn_one(int x,int y) {
        if(g[x][y]=='+')
            g[x][y]='-';
        else g[x][y]='+';
    }
    public static void turn_all(int x,int y) {
        for (int i = 0; i < 4; i++) {
            turn_one(x,i);
            turn_one(i,y);
        }
        turn_one(x,y);
    }
    public static void main(String[] args) throws IOException {
        for (int i = 0; i < 4; i++) {
            g[i]=in.readLine().toCharArray();
        }
        for (int i = 0; i < 4; i++) {
            backup[i]=g[i].clone();
        }
        for (int op = 0; op < 1<<16; op++) {
            List temp=new ArrayList<PII>();
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if((op>>get(i,j)&1)==1) {
                        turn_all(i,j);
                        temp.add(new PII(i,j));
                    }
                }
            }
            boolean dark=true;
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if(g[i][j]=='+') {
                        dark=false;
                        break;
                    }
                }
            }
            if(dark) {
                if(res.isEmpty()||res.size()>temp.size())
                    res=temp;
            }
            for (int i = 0; i < 4; i++) {
                g[i]=backup[i].clone();
            }
        }
        System.out.println(res.size());
        for (PII p:res) {
            System.out.println((p.x+1)+" "+(p.y+1));
        }
        in.close();
    }
}
class PII {
    int x;
    int y;
    public PII(int x,int y) {
        this.x=x;
        this.y=y;
    }
}
相关文章
|
4月前
|
人工智能 Java 大数据
Java程序员真的还有未来吗?如何备战2024春招?并狂拿大厂offer?
Java程序员还有未来吗? 嘿,小伙伴们,你们有没有想过Java程序员还有没有未来? 哈哈,别担心,我这就来给你们答疑解惑! 首先,让我们来看看Java的发展历程。自从Java诞生以来,它就一直是编程界的一颗璀璨明星。从Web应用到企业级应用,再到移动应用,Java无处不在。那么,现在呢?现在,随着人工智能、大数据和云计算的兴起,Java依然发挥着重要的作用。这些领域都需要大量的Java程序员来支持它们的发展。 那么,有人会说:“哎呀,现在出现了那么多新的编程语言和框架,Java程序员会不会被淘汰啊?”哈哈,别担心,Java程序员们!这些新语言和框架的出现并不会让Java消失。相反,它们
121 0
|
11月前
|
算法 Java 测试技术
【备战蓝桥杯 | 软件Java大学B组】十三届真题深刨详解(2)
【备战蓝桥杯 | 软件Java大学B组】十三届真题深刨详解(2)
52 0
|
3月前
|
Java API
备战第十五届蓝桥杯Java软件开发大学B组常见API记录
备战第十五届蓝桥杯Java软件开发大学B组常见API记录
24 0
|
11月前
|
存储 人工智能 Java
【备战蓝桥杯 | 软件Java大学B组】十三届真题深刨详解(1)
【备战蓝桥杯 | 软件Java大学B组】十三届真题深刨详解(1)
459 0
|
缓存 NoSQL 算法
【Java面试八股文宝典之Redis篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day14
【Java面试八股文宝典之Redis篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day14
298 0
【Java面试八股文宝典之Redis篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day14
|
NoSQL Java 中间件
备战金九银十:4000道Java面试真题合集,助你搞定面试官
又逢金九银十,意味着很多人又面临着就职和跳槽,相信还有很多人对于自己就职没有很大的把我,今天就给大家分享我一个朋友总结的4000到Java必问核心知识点,以及面试真题解答。
|
4月前
|
算法 网络协议 Java
备战春招狂刷这份大厂级24W字java面试手册2个月可成功逆袭上岸!
前言 2023年金九银十程序员跳槽或者找工作并不理想,迟迟找不到工作,甚至大厂还进行几轮裁员,导致整个就业市场都不是太好! 出现这种情况是因为中美贸易战,导致大环境不好、大厂裁员、就业情况差、企业要求变高、各行各业越来越卷,尤其是程序员,处于这个阶段,感觉特别明显! 对于程序员这个群体来说,java程序员的占比就非常之高,就业市场等于说是千军万马过独木桥,简直可以说是太难了!卷不过、根本卷不过! 在这里想说的是,大环境已经这样了,我们已经也无法左右这个市场,根本没有选择的余地,所以,打不过就加入,努力的提升自己能技术能力,直接吊打面试官! 这不,就迎来了大厂级24W字java面试手册!
|
算法 网络协议 Java
备战秋招狂刷这份大厂级24W字java面试手册2个月可成功逆袭上岸!
23年金三银四程序员跳槽或者找工作并不理想,迟迟找不到工作,甚至大厂还进行几轮裁员,导致整个就业市场都不是太好! 出现这种情况是因为中美贸易战,导致大环境不好、大厂裁员、就业情况差、企业要求变高、各行各业越来越卷,尤其是程序员,处于这个阶段,感觉特别明显! 对于程序员这个群体来说,java程序员的占比就非常之高,就业市场等于说是千军万马过独木桥,简直可以说是太难了!卷不过、根本卷不过! 在这里想说的是,大环境已经这样了,我们已经也无法左右这个市场,根本没有选择的余地,所以,打不过就加入,努力的提升自己能技术能力,直接吊打面试官! 这不,就迎来了大厂级24W字java面试手
78 0
|
SpringCloudAlibaba 架构师 Java
「面试小抄」2023年GitHub最热Java面试题技术点,备战金九银十
最近替公司面了几个应聘者,结果给我整抑郁了,9点的面试9点10分才到!!!这还不是最重要的,重要的是穿着一眼就让人看出来没有对这场面试很重视的感觉!!但是小编还是面完了,很多简单的源码问题+项目经验+并发处理等问题上都回答的寥寥草草,现在的年轻人。。。。。
111 0
|
Java 关系型数据库 MySQL
【Java面试八股文宝典之MySQL篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day20
【Java面试八股文宝典之MySQL篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day20
97 0
【Java面试八股文宝典之MySQL篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day20