• 算法 - 正方形数量


    题目描述

    输入N个互不相同的二维整数坐标,求这N个坐标可以构成的正方形数量。[内积为零的的两个向量垂直]

    输入描述

    第一行输入为N,N代表坐标数量,N为正整数。N <= 100

    之后的 K 行输入为坐标x y以空格分隔,x,y为整数,-10<=x, y<=10

    输出描述

    输出可以构成的正方形数量。

    用例

    输入

    3
    1 3
    2 4
    3 1

    输出0 (3个点不足以构成正方形)
    说明
    输入

    4
    0 0
    1 2
    3 1
    2 -1

    输出1
    说明

    题目解析

    其实当我们知道正方形相邻两点的坐标,即某条边的坐标后,就可以求出其余两点的坐标。

    如下图中,我们知道正方形的红色点坐标后,就画出绿色点坐标和橙色点坐标来形成两个正方形,这其中似乎隐藏着什么规律?

    我们选取其中一个正方形来分析

    我们在目标正方形外面包裹一个更大的正方形,此时可以发现大正方形和小正方形相交点切割出了相同的几个尺寸:d1和d2。

    假设已知A点坐标(x1, y1),B点坐标(x2,y2),那么

    • d1 = x1 - x2
    • d2 = y1 - y2

    其实很容易可以发现,d1含义是A,B两点横向距离,d2是A,B两点纵向距离。

    基于A,B点坐标,以及d1,d2,我们可以算出C,D点坐标分别为:

    • C坐标 (x2 + d2, y2 - d1)
    • D坐标 (x1 + d2, y1 - d1)

    继续转化一下可得:

    • C坐标 (x2 + y1 - y2, y2 - (x1 - x2))
    • D坐标 (x1 + y1 - y2, y1 - (x1 - x2))

    这是求A,B右下方向C,D边得公式推导。

    同理,可以根据A,B推导出其左上方向E,F边,图示如下:

    基于A,B点坐标,以及d1,d2,我们可以算出E,F点坐标分别为: 

    • E坐标 (x1 - d2,y1 + d1)
    • F坐标 (x2 - d2,y1 + d1)

    继续转化一下可得:

    • E坐标 (x1 - (y1 - y2),y1 + x1 - x2)
    • F坐标 (x2 - (y1 - y2),y1 + x1 - x2)

    此时我们就得到了根据正方形任意相邻两点坐标,求另外两点坐标的公式了。

    因此,接下来我们只需要遍历出两个点,然后通过公式得出另外可能的两个点,再在所有点中查找是否存在可能的两点,若存在,则正方形count++。

    最后的正方形个数squareCount 需要除以 4,原因是,如果输入中真的存在如下图中的绿色,橙色点,则遍历过程中也会将绿色,橙色点遍历出来,然后求它们的可能正方形

    也就是说上图中两个正方形,不仅会被两个红色点求出来两次次,还会被两个绿色点求出来一次,还会被两个橙色点求出来一次,还会被一绿一红求出来两次,被一橙一红求出来两次 ,总共是8次,而实际上只有2个正方形,因此最终结果要除以4。

    JavaScript算法源码

    1. /* JavaScript Node ACM模式 控制台输入获取 */
    2. const readline = require("readline");
    3. const rl = readline.createInterface({
    4. input: process.stdin,
    5. output: process.stdout,
    6. });
    7. const lines = [];
    8. let n;
    9. rl.on("line", (line) => {
    10. lines.push(line);
    11. if (lines.length === 1) {
    12. n = parseInt(lines[0]);
    13. }
    14. if (n && lines.length === n + 1) {
    15. lines.shift();
    16. console.log(getSquareCount(lines));
    17. lines.length = 0;
    18. }
    19. });
    20. /* 数学公式验证正方形 */
    21. function getSquareCount(coordinates) {
    22. let squareCount = 0;
    23. const set = new Set(coordinates);
    24. for (let i = 0; i < coordinates.length; i++) {
    25. let [x1, y1] = coordinates[i].split(" ").map((ele) => parseInt(ele));
    26. for (let j = i + 1; j < coordinates.length; j++) {
    27. let [x2, y2] = coordinates[j].split(" ").map((ele) => parseInt(ele));
    28. let x3 = x1 - (y1 - y2);
    29. let y3 = y1 + (x1 - x2);
    30. let x4 = x2 - (y1 - y2);
    31. let y4 = y2 + (x1 - x2);
    32. if (set.has(x3 + " " + y3) && set.has(x4 + " " + y4)) squareCount++;
    33. let x5 = x1 + (y1 - y2);
    34. let y5 = y1 - (x1 - x2);
    35. let x6 = x2 + (y1 - y2);
    36. let y6 = y2 - (x1 - x2);
    37. if (set.has(x5 + " " + y5) && set.has(x6 + " " + y6)) squareCount++;
    38. }
    39. }
    40. return squareCount / 4;
    41. }

    Java算法源码

    1. import java.util.Arrays;
    2. import java.util.HashSet;
    3. import java.util.Scanner;
    4. public class Main {
    5. public static void main(String[] args) {
    6. Scanner sc = new Scanner(System.in);
    7. int n = Integer.parseInt(sc.nextLine());
    8. String[] coordinates = new String[n];
    9. for (int i = 0; i < n; i++) {
    10. coordinates[i] = sc.nextLine();
    11. }
    12. System.out.println(getResult(n, coordinates));
    13. }
    14. public static int getResult(int n, String[] coordinates) {
    15. int squareCount = 0;
    16. HashSet set = new HashSet<>(Arrays.asList(coordinates));
    17. for (int i = 0; i < n; i++) {
    18. Integer[] arr1 =
    19. Arrays.stream(coordinates[i].split(" ")).map(Integer::parseInt).toArray(Integer[]::new);
    20. int x1 = arr1[0], y1 = arr1[1];
    21. for (int j = i + 1; j < n; j++) {
    22. Integer[] arr2 =
    23. Arrays.stream(coordinates[j].split(" ")).map(Integer::parseInt).toArray(Integer[]::new);
    24. int x2 = arr2[0], y2 = arr2[1];
    25. int x3 = x1 - (y1 - y2), y3 = y1 + (x1 - x2);
    26. int x4 = x2 - (y1 - y2), y4 = y2 + (x1 - x2);
    27. if (set.contains(x3 + " " + y3) && set.contains(x4 + " " + y4)) squareCount++;
    28. int x5 = x1 + (y1 - y2), y5 = y1 - (x1 - x2);
    29. int x6 = x2 + (y1 - y2), y6 = y2 - (x1 - x2);
    30. if (set.contains(x5 + " " + y5) && set.contains(x6 + " " + y6)) squareCount++;
    31. }
    32. }
    33. return squareCount / 4;
    34. }
    35. }

    Python算法源码

    1. # 输入获取
    2. n = int(input())
    3. coordinates = [input() for _ in range(n)]
    4. # 算法入口
    5. def getResult():
    6. squareCount = 0
    7. coordinatesSet = set(coordinates)
    8. for i in range(n):
    9. x1, y1 = map(int, coordinates[i].split())
    10. for j in range(i + 1, n):
    11. x2, y2 = map(int, coordinates[j].split())
    12. x3 = x1 - (y1 - y2)
    13. y3 = y1 + (x1 - x2)
    14. x4 = x2 - (y1 - y2)
    15. y4 = y2 + (x1 - x2)
    16. if f"{x3} {y3}" in coordinatesSet and f"{x4} {y4}" in coordinatesSet:
    17. squareCount += 1
    18. x5 = x1 + (y1 - y2)
    19. y5 = y1 - (x1 - x2)
    20. x6 = x2 + (y1 - y2)
    21. y6 = y2 - (x1 - x2)
    22. if f"{x5} {y5}" in coordinatesSet and f"{x6} {y6}" in coordinatesSet:
    23. squareCount += 1
    24. return squareCount // 4
    25. # 算法调用
    26. print(getResult())
  • 相关阅读:
    《棒球英豪》:青春球场·棒球1号位
    apache虚拟主机头的实现方式
    探索一些常见的存储过程奥秘
    Java 基于SpringBoot+Vue的社区医院管理系统的实现
    [AIGC] Kafka 消费者的实现原理
    [4G/5G/6G专题基础-154]: 5G无线准入控制RAC(Radio Admission Control)
    YOLOv5改进实战 | 更换主干网络Backbone(四)之轻量化模型MobileNetV3
    【python】基于python聊天工具
    [附源码]计算机毕业设计游戏交易平台Springboot程序
    .欧拉函数.
  • 原文地址:https://blog.csdn.net/qfc_128220/article/details/127417851