0
点赞
收藏
分享

微信扫一扫

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

hwwjian 2022-02-06 阅读 64

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

题目大意

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

解题思路

⭐⭐初高中学过直线的多种表达形式,这里选用点斜式,通过比较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);
    }

}

在这里插入图片描述

举报

相关推荐

0 条评论