第十二届蓝桥杯真题Java B组 【直线】

题目描述:
在平面直角坐标系中,两点可以确定一条直线。
如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。
给定平面上2 × 3 个整点{(x, y)|0 ≤ x < 2, 0 ≤ y < 3, x ∈ Z, y ∈ Z},
即横坐标是0 到1 (包含0 和1) 之间的整数、纵坐标是0 到2 (包含0 和2) 之间的整数的点。
这些点一共确定了11 条不同的直线。
给定平面上20 × 21 个整点{(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z},
即横坐标是0 到19 (包含0 和19) 之间的整数、纵坐标是0 到20 (包含0 和20) 之间的整数的点。
请问这些点一共确定了多少条不同的直线。

思路:
直接先获取每个点,然后再通过y=kx+b来确定两点之间的直线。
若是用double类型来处理斜率k,会有误差,因此直接用String的形式来表示直线,斜率直接表示为(y2-y1)/(x1-x2)的形式,但分子分母要同时除以最大公因数,来排除重复的情况。b也通过同样的方法来表示。
由于本题的点都不超过两位数,因此采用整形的x*100+y表示一个点。获取点的时候再/100或者%100来获取x和y。

获取每个点:

		List<Integer> list = new ArrayList<>();     //  存放每个点的List集合
        Set<String> res = new HashSet<>();      //  存放直线的集合,HashSet不能重复
        for (int i=0;i<20;i++) {
            for (int j = 0; j < 21; j++) {  //  每个点以i*100+j的形式存放
                list.add(i * 100 + j);
            }
        }

斜率k和b的处理:
对b的处理时,如下:
B的处理

		int len = list.size();  //  点的数量
        for (int i=0;i<len;i++){
            int dot1 = list.get(i);     //  获取当前点
            int x1 = dot1/100, y1 = dot1%100;   //  当前点的x和y值
            for (int j=i+1;j<len;j++){
                int dot2 = list.get(j); //  获取下一个点
                int x2 = dot2/100, y2 = dot2%100;   //  下一个点的x和y值
                int ky = y2-y1, kx = x2-x1;     //  y和x之差的比值就是斜率
                if (kx==0){
                    res.add("x="+x1);   //  当斜率不存在时的处理
                    continue;
                }
                int gcd1 = gcd(ky,kx);  //  获取y的差和x的差的最大公因数,以便排除同一条直线
                String K = ky/gcd1+"/"+kx/gcd1; //  K就是斜率的表示情况
                int temp = y1*kx - x1*ky;   //  用来计算切点B
                int gcd2 = gcd(temp,kx);
                String B = temp/gcd2+"/"+kx/gcd2;
                res.add(K+" "+B);   //  用K和B表示直线
            }
        }

完整代码:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class 直线2021 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();     //  存放每个点的List集合
        Set<String> res = new HashSet<>();      //  存放直线的集合,HashSet不能重复
        for (int i=0;i<20;i++) {
            for (int j = 0; j < 21; j++) {  //  每个点以i*100+j的形式存放
                list.add(i * 100 + j);
            }
        }
        int len = list.size();  //  点的数量
        for (int i=0;i<len;i++){
            int dot1 = list.get(i);     //  获取当前点
            int x1 = dot1/100, y1 = dot1%100;   //  当前点的x和y值
            for (int j=i+1;j<len;j++){
                int dot2 = list.get(j); //  获取下一个点
                int x2 = dot2/100, y2 = dot2%100;   //  下一个点的x和y值
                int ky = y2-y1, kx = x2-x1;     //  y和x之差的比值就是斜率
                if (kx==0){
                    res.add("x="+x1);   //  当斜率不存在时的处理
                    continue;
                }
                int gcd1 = gcd(ky,kx);  //  获取y的差和x的差的最大公因数,以便排除同一条直线
                String K = ky/gcd1+"/"+kx/gcd1; //  K就是斜率的表示情况
                int temp = y1*kx - x1*ky;   //  用来计算切点B
                int gcd2 = gcd(temp,kx);
                String B = temp/gcd2+"/"+kx/gcd2;
                res.add(K+" "+B);   //  用K和B表示直线
            }
        }
        System.out.println(res.size());
    }
    private static int gcd(int a, int b){   //  获取最大公约数的函数
        return b==0?a:gcd(b,a%b);
    }
}
  • 11
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Easenyang

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

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

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

打赏作者

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

抵扣说明:

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

余额充值