Java && C++ 实现第十二届蓝桥杯 C++ B组 C直线

152 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

虽然是C++组的,但是和Java组的差不了两道题,大家都可以看一看 如有错误,还请佬 评论或私信指出(写的稍些急) 再也不肝博客了 /(ㄒoㄒ)/~~

(由于上传图片有限制,如果描述不清楚点击手写题解) 手写题解字丑,但是小编感觉会比文字看的直观一些(其实是不会用数学公式)

编程题测试数据

C++B组手写题解(如果访问出错,请刷新访问的页面即可(Nebo的问题))

当前页面的编程题均在C语言网成功运行 C语言网有各届蓝桥杯的题库 第十二届蓝桥杯编程题测试 刷题集

在这里插入图片描述

试题 C: 直线

本题总分:10 分

【问题描述】

在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上,

那么这些点中任意两点确定的直线是同一条。

给定平面上 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) 之

间的整数的点。请问这些点一共确定了多少条不同的直线。

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一

个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分

请添加图片描述

package LanqiaobeiExam._12CB;

import java.util.*;

/**
 * ClassName: C直线
 * Package: LanqiaobeiExam._12CB
 *
 * @DATE: 2022/3/21 15:29
 * Author: asleep
 */
public class C直线 {	//40257
    public static class Node {
        int x, y;

        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }

        double x1, y1;

        public Node(double x1, double y1) {
            this.x1 = x1;
            this.y1 = y1;
        }


    }

    public static class Line {
        int a, b, c;

        public Line(int a, int b, int c) {
            this.a = a;
            this.b = b;
            this.c = c;
        }

        @Override
        public boolean equals(Object o) {
            Line line = (Line) o;
            return a == line.a && b == line.b && c == line.c;
        }

        @Override
        public int hashCode() {
            return Objects.hash(a, b, c);
        }
    }

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

    public static int gcd(int a, int b, int c) {
        return gcd(gcd(a, b), gcd(b, c));
    }

    public static void main(String[] args) {
        //方法一   两点式
        {

            int n = 20, m = 21;
            Set<Line> set = new HashSet<>();
            Node[] node = new Node[1000];
            int index = 0;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    node[index++] = new Node(i, j);
                }
            }
            for (int i = 0; i < index; i++) {
                for (int j = i + 1; j < index; j++) {
                    int a = node[i].y - node[j].y;//系数
                    int b = node[j].x - node[i].x;
                    int c = node[i].y * (node[i].x - node[j].x) - node[i].x * (node[i].y - node[j].y);
                    int g = gcd(Math.abs(a), Math.abs(b), Math.abs(c));
                    set.add(new Line(a / g, b / g, c / g));
                }
            }
            System.out.println(set.size());

        }

        //方法二:  y = kx+b 确定直线
        {

            List<Integer> points = new ArrayList<>();
            Set<String> ans = new HashSet<>();
            for (int i = 0; i < 20; i++) {
                for (int j = 0; j < 21; j++) {
                    points.add(i * 100 + j); //存xy
                }
            }
            int size = points.size();
            for (int i = 0; i < size; i++) {
                int node1 = points.get(i);
                int x1 = node1 / 100, y1 = node1 % 100;
                for (int j = i + 1; j < size; j++) {
                    int node2 = points.get(j);
                    int x2 = node2 / 100, y2 = node2 % 100;
                    int up = y1 - y2, down = x1 - x2;
                    if (down == 0) {
                        ans.add("x = " + x1);
                        continue;
                    }
                    int c1 = gcd(up, down);
                    String K = up / c1 + " " + down / c1;
                    int Up = y1 * down - x1 * up;
                    int c2 = gcd(Up, down);
                    String B = Up / c2 + " " + down / c2;
                    ans.add(K + " " + B);
                }
            }
            System.out.println(ans.size());

        }

        //方法三:
        {
            //两点式两个点交换后为一条新的直线,需要除 2
            Set<Line> set = new HashSet<>();
            int n = 20, m = 21;
            for (int x1 = 0; x1 < n; x1++) {
                for (int y1 = 0; y1 < m; y1++) {
                    for (int x2 = 0; x2 < n; x2++) {
                        for (int y2 = 0; y2 < m; y2++) {
                            if (x1 == x2 && y1 == y2) { //两个相同的点不能确定直线
                                continue;
                            }
                            int a =y1 - y2, b = x2 - x1;
                            int c = x1 * (y2 - y1) - y1 * (x2 - x1);
                            int g = gcd(Math.abs(a), Math.abs(b), Math.abs(c));
                            set.add(new Line(a / g, b / g, c / g));
                        }
                    }
                }
            }
            System.out.println(set.size() / 2);

        }

    }
}

#include "iostream"
#include "algorithm"
#include "cmath"

using namespace std;

struct Node {   //40257
    double k, b;
    bool operator< (const Node& node) const {  //自定义排序方法,先按照k的大小排序,k相等时按照b的大小排序
        if (k != node.k) {
            return k < node.k;
        }
        return b < node.b;
    }
}nodes[200000];;

int main() {
    int index= 0;   //遍历两个xy
    for (int x1 = 0; x1 < 20; x1++) {
        for (int y1 = 0; y1 < 21; y1++) {
            for (int x2 = 0; x2 < 20; x2++) {
                for (int y2 = 0; y2 < 21; y2++) {
                    if (x1 == x2) { //斜率是0,一共有二十条,后面直接加
                        continue;
                    }
                    double k = (double)(y2 - y1) / (x2 - x1);
                    double b = y1 - k * x1;
                    nodes[index++] = {k, b};
                }
            }
        }
    }
    sort(nodes, nodes + index);
    int res = 1;    //默认第一个就存在了
    for (int i = 1; i < index; i++) {   //小数是有误差的,当误差比10的-8次方小,我们就认为是一条直线
        if (fabs(nodes[i].k - nodes[i - 1].k) > 1e-8 || fabs(nodes[i].b - nodes[i - 1].b) > 1e-8) {
            res++;
        }
    }
    cout << res + 20;

    return 0;
}