美团研发岗 4月18号笔试真题 - 坐标

坐标(Py/Java/C++/Js/Go)题解

美团研发岗 四月十八号笔试 第二题

题目内容

在二维直角坐标系中有 nnn 个点(按输入顺序编号为 111∼nnn),每个点的横、纵坐标均为整数。

请你构造一个大小为 n×nn×nn×n 的数组 {ai,ja_{i,j}ai,j}。对任意两个不同的编号i,ji,ji,j,将线段 ijijij 围绕点 iii 旋转一周,线段的另一端点在以 iii 为圆心、半径为 ∣ij∣∣ij∣∣ij∣ 的圆盘上运动。定义ai,ja_{i,j}ai,j 为线段 ijijij 在旋转过程中扫过的区域(即以iii 为圆心、半径为 ∣ij∣∣ij∣∣ij∣ 的圆盘)内包含的、除 i,ji,ji,j 之外其他编号不同的点的数量;特别地,对所有1≤i≤n1≤i≤n1≤i≤n都有 ai,i=0a_{i,i}=0ai,i=0。

更形式化地,令点iii的坐标为 (xi,yi)(x_i,y_i)(xi,yi),则:

ai,j=#{k∈{1,...,n}∖{i,j}∣dist⁡(i,k)≤dist⁡(i,j)}.a_{i,j} = \# \left\{ k \in \{1,\dots,n\} \setminus \{i,j\} \mid \operatorname{dist}(i,k) \le \operatorname{dist}(i,j) \right\}.ai,j=#{k∈{1,...,n}∖{i,j}∣dist(i,k)≤dist(i,j)}.

输入描述

每个测试文件包含多组测试数据:第一行输入一个整数T(1≤T≤102)T(1≤T≤10^2)T(1≤T≤102),代表数据组数。每组测试数据描述如下:

  • 第一行输入一个整数 n(1≤n≤2×103)n(1≤n≤2×10^3)n(1≤n≤2×103),表示点的数量。
  • 此后共 nnn 行,每行输入两个整数 x,y(1≤x,y≤109)x,y(1≤x,y≤10^9)x,y(1≤x,y≤109),表示一个点的坐标,按输入顺序依次编号为 1,2,...,n1,2,...,n1,2,...,n。
    除此之外,保证单个测试文件的 nnn 之和不超过 2×1032×10^32×103。

输出描述

对于每一组测试数据,输出nnn 行:

  • 第iii行输出 nnn 个整数,依次为 ai,1,ai,2,...,ai,na_{i,1},a_{i,2},...,a_{i,n}ai,1,ai,2,...,ai,n;
  • 数与数之间以一个空格分隔。

样例1

输入

复制代码
2
3
1 1
2 1
1 2
4
1 1
2 1
3 1
4 1

输出

复制代码
0 1 1
0 0 1
0 1 0
0 0 1 2
1 0 1 2
2 1 0 1
2 1 0 0

题解

思路

逻辑分析

  1. 对于每组数据,预处理计算所有点之间距离的平分
  2. 从前往后枚举点作为圆心,基于圆心相同,半径越大,包含点越多的规律。
    1. 将除本身点以{距离、下标}格式用数组进行保存,然后根据距离对数组进行排序。
    2. 接下来按照距离批次进行处理,对于距离为d的包含的点的数量 = 与圆心距离距离小于d的数量 + 等于d的点数量
  3. 按照2的逻辑就能正确计算出对应结果。

C++

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

vector<vector<int>> solve(vector<pair<long,long>>& points) {
    int n = points.size();
    vector<vector<int>> ans(n, vector<int>(n, 0));
    // 预处理,统计各个点之间平方距离
    vector<vector<long>> dist(n, vector<long>(n, 0));
    // 对称的只需计算左下角
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < i; j++) {
            long dx = points[i].first - points[j].first;
            long dy = points[i].second - points[j].second;
            dist[i][j] = dx * dx  + dy * dy;
            dist[j][i] = dist[i][j];
        }
    }
    // 枚举 圆心, 圆心相同,半径越大,包含点越多
    for (int i = 0; i < n; i++) {
        vector<pair<long, int>> node;
        for (int j = 0; j < n; j++) {
            // 不考虑本身
            if (i == j) {
                continue;
            }
            node.push_back({dist[i][j], j});
        }
        
        sort(node.begin(), node.end(), [](auto& a, auto & b) {
            return a.first < b.first;
        });
        
        // 按照相同距离进行批处理
        int m = node.size();
        int l = 0;
        while (l < m) {
            int r = l;
            while (r + 1 < m && node[r + 1].first == node[r].first) {
                r++;
            }
            // [l, r]距离相同包含点相同都为r
            for (int j = l; j <= r; j++) {
                ans[i][node[j].second] = r;
            }
            l++;
        }
        
    }
    return ans;
}


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int T;
    cin >> T;
    while (T--) {
       int n;
        cin >> n;
        vector<pair<long, long>> points(n);
        for (int i = 0; i < n; i++) {
            cin >> points[i].first >> points[i].second;
        }
        vector<vector<int>> ans = solve(points);
        
        // 输出答案矩阵
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (j > 0) {
                    cout << ' ';
                }
                cout << ans[i][j];
            }
            cout << endl;
        }
        
    }
    return 0;
}

java

java 复制代码
import java.io.*;
import java.util.*;

public class Main {

    static int[][] solve(long[][] points) {
        int n = points.length;
        int[][] ans = new int[n][n];

        // 预处理,统计各个点之间平方距离
        long[][] dist = new long[n][n];

        // 对称的只需计算左下角
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                long dx = points[i][0] - points[j][0];
                long dy = points[i][1] - points[j][1];
                dist[i][j] = dx * dx + dy * dy;
                dist[j][i] = dist[i][j];
            }
        }

        // 枚举圆心,圆心相同,半径越大,包含点越多
        for (int i = 0; i < n; i++) {
            List<long[]> node = new ArrayList<>();

            for (int j = 0; j < n; j++) {
                // 不考虑本身
                if (i == j) {
                    continue;
                }
                node.add(new long[]{dist[i][j], j});
            }

            node.sort((a, b) -> Long.compare(a[0], b[0]));

            // 按照相同距离进行批处理
            int m = node.size();
            int l = 0;

            while (l < m) {
                int r = l;

                while (r + 1 < m && node.get(r + 1)[0] == node.get(r)[0]) {
                    r++;
                }

                // [l, r]距离相同包含点相同都为r
                for (int j = l; j <= r; j++) {
                    ans[i][(int) node.get(j)[1]] = r;
                }

                l = r + 1;
            }
        }

        return ans;
    }

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder out = new StringBuilder();

        int T = Integer.parseInt(br.readLine());

        while (T-- > 0) {
            int n = Integer.parseInt(br.readLine());

            long[][] points = new long[n][2];

            for (int i = 0; i < n; i++) {
                String[] arr = br.readLine().split(" ");
                points[i][0] = Long.parseLong(arr[0]);
                points[i][1] = Long.parseLong(arr[1]);
            }

            int[][] ans = solve(points);

            // 输出答案矩阵
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if (j > 0) {
                        out.append(' ');
                    }
                    out.append(ans[i][j]);
                }
                out.append('\n');
            }
        }

        System.out.print(out);
    }
}

python

python 复制代码
import sys

input = sys.stdin.readline


def solve(points):
    n = len(points)

    ans = [[0] * n for _ in range(n)]

    # 预处理,统计各个点之间平方距离
    dist = [[0] * n for _ in range(n)]

    # 对称的只需计算左下角
    for i in range(n):
        for j in range(i):
            dx = points[i][0] - points[j][0]
            dy = points[i][1] - points[j][1]

            dist[i][j] = dx * dx + dy * dy
            dist[j][i] = dist[i][j]

    # 枚举圆心,圆心相同,半径越大,包含点越多
    for i in range(n):
        node = []

        for j in range(n):
            # 不考虑本身
            if i == j:
                continue

            node.append((dist[i][j], j))

        node.sort()

        # 按照相同距离进行批处理
        m = len(node)
        l = 0

        while l < m:
            r = l

            while r + 1 < m and node[r + 1][0] == node[r][0]:
                r += 1

            # [l, r]距离相同包含点相同都为r
            for j in range(l, r + 1):
                ans[i][node[j][1]] = r

            l = r + 1

    return ans


T = int(input())

for _ in range(T):
    n = int(input())

    points = []

    for _ in range(n):
        x, y = map(int, input().split())
        points.append((x, y))

    ans = solve(points)

    # 输出答案矩阵
    for row in ans:
        print(*row)

javascript

js 复制代码
const readline = require("readline");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

const input = [];

rl.on("line", (line) => {
    input.push(line.trim());
});

rl.on("close", () => {
    let idx = 0;

    const T = Number(input[idx++]);

    function solve(points) {
        const n = points.length;

        const ans = Array.from({ length: n }, () => Array(n).fill(0));

        // 预处理,统计各个点之间平方距离
        const dist = Array.from({ length: n }, () => Array(n).fill(0));

        // 对称的只需计算左下角
        for (let i = 0; i < n; i++) {
            for (let j = 0; j < i; j++) {
                const dx = points[i][0] - points[j][0];
                const dy = points[i][1] - points[j][1];

                dist[i][j] = dx * dx + dy * dy;
                dist[j][i] = dist[i][j];
            }
        }

        // 枚举圆心,圆心相同,半径越大,包含点越多
        for (let i = 0; i < n; i++) {
            const node = [];

            for (let j = 0; j < n; j++) {
                // 不考虑本身
                if (i === j) {
                    continue;
                }

                node.push([dist[i][j], j]);
            }

            node.sort((a, b) => a[0] - b[0]);

            // 按照相同距离进行批处理
            const m = node.length;
            let l = 0;

            while (l < m) {
                let r = l;

                while (r + 1 < m && node[r + 1][0] === node[r][0]) {
                    r++;
                }

                // [l, r]距离相同包含点相同都为r
                for (let j = l; j <= r; j++) {
                    ans[i][node[j][1]] = r;
                }

                l = r + 1;
            }
        }

        return ans;
    }

    const output = [];

    for (let tc = 0; tc < T; tc++) {
        const n = Number(input[idx++]);

        const points = [];

        for (let i = 0; i < n; i++) {
            const [x, y] = input[idx++].split(" ").map(Number);
            points.push([x, y]);
        }

        const ans = solve(points);

        // 输出答案矩阵
        for (let i = 0; i < n; i++) {
            output.push(ans[i].join(" "));
        }
    }

    console.log(output.join("\n"));
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
)

func solve(points [][2]int64) [][]int {
	n := len(points)

	ans := make([][]int, n)
	for i := range ans {
		ans[i] = make([]int, n)
	}

	// 预处理,统计各个点之间平方距离
	dist := make([][]int64, n)
	for i := range dist {
		dist[i] = make([]int64, n)
	}

	// 对称的只需计算左下角
	for i := 0; i < n; i++ {
		for j := 0; j < i; j++ {
			dx := points[i][0] - points[j][0]
			dy := points[i][1] - points[j][1]

			dist[i][j] = dx*dx + dy*dy
			dist[j][i] = dist[i][j]
		}
	}

	type Pair struct {
		dist int64
		idx  int
	}

	// 枚举圆心,圆心相同,半径越大,包含点越多
	for i := 0; i < n; i++ {
		node := make([]Pair, 0, n-1)

		for j := 0; j < n; j++ {
			// 不考虑本身
			if i == j {
				continue
			}

			node = append(node, Pair{dist[i][j], j})
		}

		sort.Slice(node, func(a, b int) bool {
			return node[a].dist < node[b].dist
		})

		// 按照相同距离进行批处理
		m := len(node)
		l := 0

		for l < m {
			r := l

			for r+1 < m && node[r+1].dist == node[r].dist {
				r++
			}

			// [l, r]距离相同包含点相同都为r
			for j := l; j <= r; j++ {
				ans[i][node[j].idx] = r
			}

			l = r + 1
		}
	}

	return ans
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	var T int
	fmt.Fscan(in, &T)

	for ; T > 0; T-- {
		var n int
		fmt.Fscan(in, &n)

		points := make([][2]int64, n)

		for i := 0; i < n; i++ {
			fmt.Fscan(in, &points[i][0], &points[i][1])
		}

		ans := solve(points)

		// 输出答案矩阵
		for i := 0; i < n; i++ {
			for j := 0; j < n; j++ {
				if j > 0 {
					fmt.Fprint(out, " ")
				}
				fmt.Fprint(out, ans[i][j])
			}
			fmt.Fprintln(out)
		}
	}
}
相关推荐
有点。2 小时前
C++倍增法(练习题)
c++·算法
智者知已应修善业3 小时前
【51单片机8位数码管同时倒计时从9999】2024-1-25
c++·经验分享·笔记·算法·51单片机
洛水水3 小时前
【力扣100题】86.柱状图中最大的矩形
算法·leetcode·职场和发展
渡之3 小时前
GRiM-Net 深度解析 | 无人机 GNSS 拒止场景下两阶段跨视角视觉定位框架
深度学习·算法·动态规划·无人机
测试仪器廖生135902563853 小时前
罗德与施瓦茨 FSP13频谱分析仪FSP30
网络·人工智能·算法
happymaker06263 小时前
LeetCodeHot100——560.和为K的子数组
算法
dtq04244 小时前
C语言刷题数组5,6(求平均值,求最大值)
c语言·数据结构·算法
郭梧悠4 小时前
Hash算法入门Hash冲突解决方案
算法·哈希算法
洛水水4 小时前
【力扣100题】81.寻找两个正序数组的中位数
数据结构·算法·leetcode