【每日真题,备战蓝桥Java】直线+路径

博主分享了备战蓝桥杯大赛的Java编程学习心得,详细解析了第十二届B组的两个真题——C.直线和E.路径。C题通过计算斜率和截距解决直线问题,使用HashSet去重;E题运用Floyd算法求解最短路径。文章提供了完整的解题思路和代码实现,并鼓励读者复习数学知识和加强算法实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在开篇:
蓝桥杯大赛即将到来,倒计时36天!
do(学习真题+理解真题+会做真题+总结真题)
while(时间!=0)
宝剑锋从磨砺出,梅花香自苦寒来。
争取冲出省赛,加油!

今天带来的是第十二届B组的两道真题的个人题解,如果有不当之处,还请各位朋友指正,下面就让我们开始吧。

C.直线(十二届真题)

在这里插入图片描述

解题思路

本题也是一个数学问题,需要回忆之前学过的数学知识,例如如何计算斜率和求截距。

解题思路是先获得所有的点,再根据两两不同的点去计算直线,用的斜截式 y = kx + b和两点式(y1-y2)=k(x1-x2),然后得到所有的 k 和 b,并去重,去重我用的是HashSet

1,对于点坐标的表示,我是用的是x扩大100倍来和y进行分隔。

for(int i=0;i<=19;i++){
         for(int j=0;j<21;j++){
             set.add(i*100+j);
         }
     }

2,获取点x,y坐标的方法如下(a,b分别为点的坐标)

int x1=a/100,x2=b/100,y1=a%100,y2=b%100;

3,获取了点的x,y坐标后,我们就可以来计算斜率了,这里用的是两点式。

             int up=y1-y2,down=x1-x2;
             int c1=gcd(up,down);
             String k=(up/c1)+" "+(down/c1);//这里求的是斜率,这个斜率表示有点奇怪,就是x的差值和y的差值拼凑

这里我们我们还需要用一下最大公约数,因为例如up=4,down=2,和up=8,down=4,计算出来的斜率是一样的,这俩种情况的取值可能会出现在一条直线上。

//返回值则是a和b的最大公约数
int gcd(int a,int b){
		return b == 0 ? a:gcd(b,a%b);
}

4,我们还要将斜率不存在的情况单独拿出来讨论。

              if(down==0){//判断斜率不存在的直线
                 count++;//这个变量是我用来统计有多少条垂直于x轴的直线,HashSet类型的ans用来去重
                 ans.add("x="+x1);
                 continue;
             }

5.接下来我们来计算截距。

 //下面的步骤会涉及到求直线方程的俩点式和点斜式,要注意这俩个公式的结合使用,不然可能第一眼看完会后可能会有一点懵
 //上面我们求的了斜率,我们随便带入一个点来求截距
             int kb=y1*down-up*x1;
             int c2=gcd(kb,down);
            String B=(kb/c2)+" "+(down/c2);//求的是截距
            ans.add(k+" "+B);//(k+" "+B)这样一个字符串用来表示一条直线
完整代码
 public static int gcd(int a,int b) {
        return b==0?a:gcd(b,a%b);
    }
    static int count=0;
    public static void main(String[] args) {
        HashSet<Integer> set=new HashSet<>();
        HashSet<String> ans=new HashSet<>();
     for(int i=0;i<=19;i++){
         for(int j=0;j<21;j++){
             set.add(i*100+j);
         }
     }
        List<Integer> arr=new ArrayList<>(set);
     int len=arr.size();
     for(int i=0;i<len;i++){
         int a=arr.get(i);
         for(int j=i+1;j<len;j++){
             int b=arr.get(j);
             int x1=a/100,x2=b/100,y1=a%100,y2=b%100;
             int up=y1-y2,down=x1-x2;
             int c1=gcd(up,down);
             String k=(up/c1)+" "+(down/c1);//这里求的是斜率,这个斜率表示有点奇怪,就是x的差值和y的差值拼凑
             if(down==0){//判断斜率不存在的直线
                 count++;
                 ans.add("x="+x1);
                 continue;//将垂直于x轴的直线添加进去,应该是有19条
             }
             //下面的步骤会涉及到求直线方程的俩点式和点斜式,要注意这俩个公式,不然可能第一眼看完会懵
             //上面我们求的了斜率,我们随便带入一个点来求截距
             int kb=y1*down-up*x1;
             int c2=gcd(kb,down);
            String B=(kb/c2)+" "+(down/c2);
            ans.add(k+" "+B);
         }
     }
        System.out.println(count);
        System.out.println(ans.size());

    }

本题难度总体来说还是不大的,就是写题之前要将数学知识好好回顾一下感觉。

E.路径(十二届真题)

在这里插入图片描述

解题思路

看完题就懵了,熟悉,但不会(尬笑),听过很多次它的大名——最短路径,然后就去恶补了一波求最小路径的方法。

本题解用的是Floyd(弗洛伊德)方法。

下面介绍一下这个算法的思想:

(一)算法思想:
Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)。从任意节点i到任意节点j的最短路径不外乎2种可能,一是直接从i到j,二是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

知道该用的算法后,本题就比较好解了,直接套用这个算法思想的模板就好(当然模板需要不断敲才能熟悉,还是要coding(哭笑)),下面直接展示代码了。

完整代码
public class 第五题路径 {

        static int[][] graph = new int[2022][2022];
        static final int INF = 0x3f3f3f3f;//这个数表示的是无穷大

        private static void floyd() {
            for (int k = 1; k <= 2021; k++) {
                for (int i = 1; i <= 2021; i++) {
                    for (int j = 1; j <= 2021; j++) {
                        if (i != j && graph[i][j] > graph[i][k] + graph[k][j]) {
                            graph[i][j] = graph[i][k] + graph[k][j];
                        }
                    }
                }
            }
        }

        private static int gcd(int a, int b) {
            return b == 0 ? a : gcd(b, a % b);
        }

        public static void main(String[] args) {
            for (int i = 1; i <= 2021; i++) {
                for (int j = 1; j <= 2021; j++) {
                    graph[i][j] = INF;
                }
            }

            for (int i = 1; i <= 2021; i++) {
                int st = Math.max(i - 21, 1);//这么写是因为差值<=21的点之间才有直接相连的边
                for (int j = st; j <= i; j++) {
                    int div = gcd(j, i);
                    int lcm = i * j / div;//无向边的大小
                    graph[i][j] = lcm;
                    graph[j][i] = lcm;
                }
            }

            floyd();

            System.out.println(graph[1][2021]); // 10266837
        }

    }

结果要跑一会才可以出来。

总结:现阶段独立自主解出来还是比较困难,继续努力。

明天继续,冲冲冲!

在这里插入图片描述

评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Brother汤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值