【绕线画】

564 篇文章

已下架不支持订阅

470 篇文章

已下架不支持订阅

题目描述

绕线画是一种在木板上钉入图钉,然后用线在图钉之间缠绕,组成几何图形的艺术。

阿甘最近正在学习绕线画,但是由于是初学者,因此需要在木板上画一个网格坐标系,然后在特定坐标点上钉入图钉。

现在木板上有一些图钉,而阿甘只能缠绕出一些简单几何图形,比如正方形,请你帮助阿甘计算出基于现有图钉,能缠绕出多少种不同的正方形,并输出这些正方形四个点的坐标信息。

输入描述

输入一个二维数组,数组元素是坐标信息 [x, y],格式如下:

[[0, 0], [4, 4], [4, -4], [8, 0], [-4, 4], [0, 8]]

最多输入 200 个坐标。

输出描述

第一行输出阿甘可以缠绕出多少种不同正方形。

之后每行输出一种可以缠绕出的正方形的坐标信息。格式如下:

[[0, 0], [0, 8], [4, -4], [4, 4]]

顺序要求:

  • 正方形内部坐标之间,都按照横坐标升序,若横坐标相同,则按照纵坐标升序。
  • 不同正方形之间,按照首个坐标的横坐标升序,若横坐标相同,则按照纵坐标升序,若都相同,继续按相同逻辑比较下一个坐标。

用例

输入[[0, 0], [4, 4], [4, -4], [8, 0], [-4, 4], [0, 8]]
输出

2

[[-4, 4], [0,0], [4, 4], [8, 0]]

[[0, 0], [0, 8], [4, -4], [4, 4]]

说明

题目解析

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

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

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

我们在目标正方形外面包裹一个更大的正方形,此时可以发现大正方形和小正方形相交点切割出了相同的几个尺寸: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,y2 + d1)

继续转化一下可得:

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

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

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

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

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

JS算法源码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
  const coordinates = JSON.parse(await readline());

  const set = new Set();
  for (let [x, y] of coordinates) {
    set.add(x + " " + y);
  }

  const squares = [];

  for (let i = 0; i < coordinates.length; i++) {
    let [x1, y1] = coordinates[i];

    for (let j = i + 1; j < coordinates.length; j++) {
      let [x2, y2] = coordinates[j];

      let x3 = x1 - (y1 - y2);
      let y3 = y1 + (x1 - x2);
      let x4 = x2 - (y1 - y2);
      let y4 = y2 + (x1 - x2);
      if (set.has(x3 + " " + y3) && set.has(x4 + " " + y4)) {
        squares.push([
          [x1, y1],
          [x2, y2],
          [x3, y3],
          [x4, y4],
        ]);
      }

      let x5 = x1 + (y1 - y2);
      let y5 = y1 - (x1 - x2);
      let x6 = x2 + (y1 - y2);
      let y6 = y2 - (x1 - x2);
      if (set.has(x5 + " " + y5) && set.has(x6 + " " + y6)) {
        squares.push([
          [x1, y1],
          [x2, y2],
          [x5, y5],
          [x6, y6],
        ]);
      }
    }
  }

  console.log(squares.length / 4);

  // 正方形内部坐标排序
  squares.forEach((square) =>
    square.sort(([x1, y1], [x2, y2]) => (x1 != x2 ? x1 - x2 : y1 - y2))
  );

  // 正方形之间排序
  squares.sort((a, b) => {
    for (let i = 0; i < 4; i++) {
      const [x1, y1] = a[i];
      const [x2, y2] = b[i];

      if (x1 != x2) return x1 - x2;
      else if (y1 != y2) return y1 - y2;
    }
    return 0;
  });

  // 去重打印
  let pre = "";
  for (let [[x1, y1], [x2, y2], [x3, y3], [x4, y4]] of squares) {
    const cur = `[[${x1}, ${y1}], [${x2}, ${y2}], [${x3}, ${y3}], [${x4}, ${y4}]]`;

    if (cur != pre) {
      console.log(cur);
      pre = cur;
    }
  }
})();

Java算法源码

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int[][] coordinates = parse(sc.nextLine());

        HashSet<String> set = new HashSet<>();
        for (int[] coordinate : coordinates) {
            int x = coordinate[0];
            int y = coordinate[1];
            set.add(x + " " + y);
        }

        ArrayList<int[][]> squares = new ArrayList<>();

        for (int i = 0; i < coordinates.length; i++) {
            int x1 = coordinates[i][0], y1 = coordinates[i][1];

            for (int j = i + 1; j < coordinates.length; j++) {
                int x2 = coordinates[j][0], y2 = coordinates[j][1];

                int x3 = x1 - (y1 - y2), y3 = y1 + (x1 - x2);
                int x4 = x2 - (y1 - y2), y4 = y2 + (x1 - x2);
                if (set.contains(x3 + " " + y3) && set.contains(x4 + " " + y4)) {
                    squares.add(new int[][]{{x1, y1}, {x2, y2}, {x3, y3}, {x4, y4}});
                }

                int x5 = x1 + (y1 - y2), y5 = y1 - (x1 - x2);
                int x6 = x2 + (y1 - y2), y6 = y2 - (x1 - x2);
                if (set.contains(x5 + " " + y5) && set.contains(x6 + " " + y6)) {
                    squares.add(new int[][]{{x1, y1}, {x2, y2}, {x5, y5}, {x6, y6}});
                }
            }
        }

        System.out.println(squares.size() / 4);

        for (int[][] square : squares) {
            // 正方形内部坐标排序
            Arrays.sort(square, (a, b) -> {
                int x1 = a[0], y1 = a[1];
                int x2 = b[0], y2 = b[1];
                return x1 != x2 ? x1 - x2 : y1 - y2;
            });
        }

        // 正方形之间排序
        squares.sort((a, b) -> {
            for (int i = 0; i < 4; i++) {
                int x1 = a[i][0], y1 = a[i][1];
                int x2 = b[i][0], y2 = b[i][1];

                if (x1 != x2) return x1 - x2;
                else if (y1 != y2) return y1 - y2;
            }
            return 0;
        });

        // 去重打印
        String pre = "";
        for (int[][] square : squares) {
            StringJoiner sj = new StringJoiner(", ", "[", "]");
            for (int i = 0; i < 4; i++) {
                int x = square[i][0];
                int y = square[i][1];
                sj.add("[" + x + ", " + y + "]");
            }
            String cur = sj.toString();

            if (!cur.equals(pre)) {
                System.out.println(cur);
                pre = cur;
            }
        }
    }

    public static int[][] parse(String s) {
        String[] subs = s.substring(1, s.length() - 2).split("], ");
        return Arrays.stream(subs).map(sub -> Arrays.stream(sub.substring(1).split(", ")).mapToInt(Integer::parseInt).toArray()).toArray(int[][]::new);
    }
}

Python算法源码

if __name__ == '__main__':
    coordinates = eval(input())
    n = len(coordinates)

    coordinatesSet = set()
    for x, y in coordinates:
        coordinatesSet.add(f"{x} {y}")

    squares = []

    for i in range(n):
        x1, y1 = coordinates[i]
        for j in range(i + 1, n):
            x2, y2 = coordinates[j]

            x3 = x1 - (y1 - y2)
            y3 = y1 + (x1 - x2)

            x4 = x2 - (y1 - y2)
            y4 = y2 + (x1 - x2)

            if f"{x3} {y3}" in coordinatesSet and f"{x4} {y4}" in coordinatesSet:
                squares.append([[x1, y1], [x2, y2], [x3, y3], [x4, y4]])

            x5 = x1 + (y1 - y2)
            y5 = y1 - (x1 - x2)

            x6 = x2 + (y1 - y2)
            y6 = y2 - (x1 - x2)

            if f"{x5} {y5}" in coordinatesSet and f"{x6} {y6}" in coordinatesSet:
                squares.append([[x1, y1], [x2, y2], [x5, y5], [x6, y6]])

    print(len(squares) // 4)

    for square in squares:
        # 正方形内部坐标排序
        square.sort()

    # 正方形之间排序
    squares.sort()

    # 去重打印
    pre = ""
    for square in squares:
        x1, y1 = square[0]
        x2, y2 = square[1]
        x3, y3 = square[2]
        x4, y4 = square[3]

        cur = f"[[{x1}, {y1}], [{x2}, {y2}], [{x3}, {y3}], [{x4}, {y4}]]"

        if cur != pre:
            print(cur)
            pre = cur

C算法源码

#include<stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#define MAX_N 2000

int squares[MAX_N][4][2];
int squares_size = 0;

int cmp1(const void *a, const void *b) {
    int *A = (int *) a;
    int *B = (int *) b;

    int x1 = A[0], y1 = A[1];
    int x2 = B[0], y2 = B[1];

    return x1 != x2 ? x1 - x2 : y1 - y2;
}

int cmp2(const void *a, const void *b) {

    for (int i = 0; i < 4; i++) {
        int x1 = (*(int (*)[4][2]) a)[i][0];
        int y1 = (*(int (*)[4][2]) a)[i][1];
        int x2 = (*(int (*)[4][2]) b)[i][0];
        int y2 = (*(int (*)[4][2]) b)[i][1];

        if (x1 != x2) {
            return x1 - x2;
        } else if (y1 != y2) {
            return y1 - y2;
        }
    }

    return 0;
}

int main() {
    int coordinates[MAX_N][2];
    int n = 0;

    while (1) {
        getchar();
        getchar();
        scanf("%d", &coordinates[n][0]);
        getchar();
        getchar();
        scanf("%d", &coordinates[n][1]);
        n++;
        getchar();
        if (getchar() != ',') break;
    }

    for (int i = 0; i < n; i++) {
        int x1 = coordinates[i][0];
        int y1 = coordinates[i][1];

        for (int j = i + 1; j < n; j++) {
            int x2 = coordinates[j][0];
            int y2 = coordinates[j][1];

            int x3 = x1 - (y1 - y2), y3 = y1 + (x1 - x2);
            int x4 = x2 - (y1 - y2), y4 = y2 + (x1 - x2);
            bool has3 = false;
            bool has4 = false;

            int x5 = x1 + (y1 - y2), y5 = y1 - (x1 - x2);
            int x6 = x2 + (y1 - y2), y6 = y2 - (x1 - x2);
            bool has5 = false;
            bool has6 = false;

            for (int k = 0; k < n; k++) {
                if (x3 == coordinates[k][0] && y3 == coordinates[k][1]) {
                    has3 = true;
                }

                if (x4 == coordinates[k][0] && y4 == coordinates[k][1]) {
                    has4 = true;
                }

                if (x5 == coordinates[k][0] && y5 == coordinates[k][1]) {
                    has5 = true;
                }

                if (x6 == coordinates[k][0] && y6 == coordinates[k][1]) {
                    has6 = true;
                }
            }

            if (has3 && has4) {
                squares[squares_size][0][0] = x1;
                squares[squares_size][0][1] = y1;
                squares[squares_size][1][0] = x2;
                squares[squares_size][1][1] = y2;
                squares[squares_size][2][0] = x3;
                squares[squares_size][2][1] = y3;
                squares[squares_size][3][0] = x4;
                squares[squares_size][3][1] = y4;
                squares_size++;
            }

            if (has5 && has6) {
                squares[squares_size][0][0] = x1;
                squares[squares_size][0][1] = y1;
                squares[squares_size][1][0] = x2;
                squares[squares_size][1][1] = y2;
                squares[squares_size][2][0] = x5;
                squares[squares_size][2][1] = y5;
                squares[squares_size][3][0] = x6;
                squares[squares_size][3][1] = y6;
                squares_size++;
            }
        }
    }

    printf("%d\n", squares_size / 4);

    for (int i = 0; i < squares_size; i++) {
        qsort(squares[i], 4, sizeof(squares[i][0]), cmp1);
    }

    qsort(squares, squares_size, sizeof(squares[0]), cmp2);

    char pre[MAX_N] = {'\0'};
    for (int i = 0; i < squares_size; i++) {
        char cur[MAX_N] = {'\0'};
        strcat(cur, "[");

        for (int j = 0; j < 4; j++) {
            int x = squares[i][j][0];
            int y = squares[i][j][1];

            char tmp[100] = {'\0'};
            sprintf(tmp, "[%d, %d], ", x, y);

            strcat(cur, tmp);
        }

        cur[strlen(cur) - 2] = ']';
        cur[strlen(cur) - 1] = '\0';

        if (strcmp(cur, pre) != 0) {
            puts(cur);
            strcpy(pre, cur);
        }
    }

    return 0;
}

C++算法源码

#include <bits/stdc++.h>

using namespace std;

int main() {
    vector<vector<int>> coordinates;
    set<string> coordinatesSet;

    while (true) {
        int x, y;
        getchar();
        getchar();
        cin >> x;
        getchar();
        getchar();
        cin >> y;
        coordinates.emplace_back(vector<int>{x, y});
        coordinatesSet.insert(to_string(x) + " " + to_string(y));
        getchar();
        if (getchar() != ',') break;
    }

    vector<vector<vector<int>>> squares;

    for (int i = 0; i < coordinates.size(); i++) {
        int x1 = coordinates[i][0];
        int y1 = coordinates[i][1];

        for (int j = i + 1; j < coordinates.size(); j++) {
            int x2 = coordinates[j][0];
            int y2 = coordinates[j][1];

            int x3 = x1 - (y1 - y2), y3 = y1 + (x1 - x2);
            int x4 = x2 - (y1 - y2), y4 = y2 + (x1 - x2);

            if (coordinatesSet.count(to_string(x3) + " " + to_string(y3)) > 0 &&
                coordinatesSet.count(to_string(x4) + " " + to_string(y4)) > 0) {
                squares.emplace_back(vector<vector<int>>{{x1, y1},
                                                         {x2, y2},
                                                         {x3, y3},
                                                         {x4, y4}});
            }

            int x5 = x1 + (y1 - y2), y5 = y1 - (x1 - x2);
            int x6 = x2 + (y1 - y2), y6 = y2 - (x1 - x2);

            if (coordinatesSet.count(to_string(x5) + " " + to_string(y5)) > 0 &&
                coordinatesSet.count(to_string(x6) + " " + to_string(y6)) > 0) {
                squares.emplace_back(vector<vector<int>>{{x1, y1},
                                                         {x2, y2},
                                                         {x5, y5},
                                                         {x6, y6}});
            }
        }
    }

    cout << squares.size() / 4 << endl;

    for (vector<vector<int>> &square: squares) {
        // 正方形内部坐标排序
        sort(square.begin(), square.end(), [](vector<int> &a, vector<int> &b) {
            int x1 = a[0], y1 = a[1];
            int x2 = b[0], y2 = b[1];
            return x1 != x2 ? x1 < x2 : y1 < y2;
        });
    }

    // 正方形之间排序
    sort(squares.begin(), squares.end(), [](vector<vector<int>> &a, vector<vector<int>> &b) {
        for (int i = 0; i < 4; i++) {
            int x1 = a[i][0], y1 = a[i][1];
            int x2 = b[i][0], y2 = b[i][1];

            if (x1 != x2) {
                return x1 < x2;
            } else if (y1 != y2) {
                return y1 < y2;
            }
        }
        return false;
    });

    // 去重打印
    string pre;
    
    for (const auto &square: squares) {
        string cur = "[[" + to_string(square[0][0]) + ", " + to_string(square[0][1]) + "]";

        for (int i = 1; i < 4; i++) {
            string tmp = ", [" + to_string(square[i][0]) + ", " + to_string(square[i][1]) + "]";
            cur += tmp;
        }
        cur += "]";

        if (cur != pre) {
            cout << cur << endl;
            pre = cur;
        }
    }

    return 0;
}

已下架不支持订阅

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员阿甘

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

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

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

打赏作者

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

抵扣说明:

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

余额充值