蓝桥杯2021年真题演练——2、直线(JavaA组)

上一题:1、相乘(JavaA组)

题目大意

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

⭐⭐在平面直角坐标系中,两点可以确定一条直线。
⭐⭐给定平面上 20 × 21​ 个整点 {(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z}​,即横坐标是 0到 19​ (包含 0​ 和 19​) 之间的整数、纵坐标是 0​ 到 20​ (包含 0​ 和 20​​) 之 间的整数的点。
请问这些点一共确定了多少条不同的直线?
答案:40257

解题思路

⭐⭐初高中学过直线的多种表达形式,这里选用点斜式,通过比较k和b区分直线。用java的话,我们可以把k和b存入HashSet中,使得重复的直线只储存一个数据。
⭐⭐关键点及注意事项:

🌙 斜率不存在的直线要另外考虑
🌙k和b可能是小数,而小数在计算机中是有精度的,直接存小数,哪怕用double型也可能不准确。所以我们用分数存储k和b,即k=kup/kdown;b=bup/bdown;且要用最简分数表示,否则不好比较是否相同。其中b可以通过一个点和k计算而得。
🌙以kup+" “+Kdown+” “+bup+” "+bdown的字符串形式将直线存入HashSet。没有斜率的直线用x=n的形式存储
🌙求最简分数可以先通过求分子分母的最大公约数,再同时除以最大公约数。我的代码中最大公约数用辗转相除法求得。
🌙把坐标存入容器ArrayList中,形式是x*100+y(一个int型的数据)这个数对除以100就是横坐标,对100取余就是纵坐标。然后再一个双重循环,就可以计算直线了。

代码解析

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        HashSet<String> kb=new HashSet<String>();//存k和b(kup kdown bup bdown)
        int x=0;//横坐标
        int y=0;//纵坐标
        /*把坐标以x*100+y的形式存入ArrayList*/
        HashSet<Integer> al=new HashSet<>();
        for(x=0;x<20;x++){
            for(y=0;y<21;y++){
                al.add(x*100+y);
            }
        }
        List<Integer> arr = new ArrayList<>(al);
        //用点斜式标识一条直线
        for(int i=0;i<x*y;i++){
            int x1=arr.get(i)/100;//点一横坐标
            int y1=arr.get(i)%100;//点一纵坐标
            for(int j=i+1;j<x*y;j++){
                int x2=arr.get(j)/100;//点二横坐标
                int y2=arr.get(j)%100;//点二纵坐标
                /*计算斜率(用分数(kup/kdown)表示)*/
                int kup=y1-y2;
                int kdown=x1-x2;
                if(kdown==0){
                    //kdown=0说明斜率不存在
                    String s="y="+x1;
                    kb.add(s);
                }else{
                    int kgcd=gcd(kup,kdown);//分子分母最大公约数
                    kup=kup/kgcd;
                    kdown=kdown/kgcd;//得到最简分数
                    //计算截距(用分数(bup/bdown)表示)
                    int bup=y1*kdown-kup*x1;
                    int bdown=kdown;
                    int bgcd=gcd(bup,bdown);//分子分母最大公约数
                    bup=bup/bgcd;
                    bdown=bdown/bgcd;//得到最简分数
                    //以kup+" "+Kdown+" "+bup+" "+bdown的形式存储一条直线
                    String s=kup+" "+kdown+" "+bup+" "+bdown;
                    kb.add(s);
                }
            }
        }
        //kb中的元素是不重复的,有重复也只会存储其中一个,因此kb的大小就是直线的个数
        System.out.println(kb.size());
    }
    //辗转相除求最大公约数
    static int gcd(int a, int b) {
        if(b==0){
            return a;
        }
        return gcd(b,a%b);
    }

}

下一题:3、货物摆放(JavaA组)
在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值