• 恒星的正方形问题


     一 原问题描述

    Squares - POJ 2002 - Virtual Judgehttps://vjudge.net/problem/POJ-2002

    二 输入和输出

    1 输入

    输入包含多个测试用例。每个测试用例都以整数 n 开始,表示恒星的数量,接下来的 n 行,每行都包含一颗恒星的 x 和 y 坐标(两个整数)。假设这些横恒星的位置是不同的,并且坐标小于 20000.当 n = 0 时,输入终止。

    2 输出

    对于每个测试用例,都单行输出恒星形成的正方形数。

    三 输入和输出样例

    1 输入样例

    4

    1 0

    0 1

    1 1

    0 0

    9

    0 0

    1 0

    2 0

    0 2

    1 2

    2 2

    0 1

    1 1

    2 1

    4

    -2 5

    3 7

    0 0

    5 2

    0

    2 输出样例

    1

    6

    1

    四 分析

    如果枚举 4 个节点会超时,可以任意枚举两个点,然后将另两个点算出来,判断是否在已创建的 hash 表里即可,首先枚举(x1,y1)、(x2、y2)两个点,然后以这两个点为边,将所有的左侧和右侧两个点都枚举一次。有以下两种情况,如下图所示,因为正方形内部的几个三角形是相等的,所以可以推导出正方形的另外两个节点(x3,y3)和(x4,y4)。

    左侧两点

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

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

    右侧两点

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

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

    五 算法设计

    1 把输入数据放入哈希表

    2 根据两个点(x1,y1)、(x2,y2),得到左侧两个点(x3,y3)、(x4、y4),在哈希表中查找这两个点是否存在,如果存在,则 ans++。

    3 根据两个点(x1,y1)、(x2,y2),得到左侧两个点(x3,y3)、(x4、y4),在哈希表中查找这两个点是否存在,如果存在,则 ans++。

    4 计数时对每个正方形都计数了两次,所以答案除以 2。因为根据两个点(x3,y3)、(x4、y4)也可以得到另外两个点(x1,y1)、(x2、y2).

    六 代码

    1. package poj2002;
    2. import java.util.Scanner;
    3. public class Poj2002 {
    4. static int N = 1010;
    5. static int H = 10007;
    6. static int sx[] = new int[N];
    7. static int sy[] = new int[N];
    8. static Node node[] = new Node[N];
    9. static int n;
    10. static int cur;
    11. static int hashTable[] = new int[H];
    12. static long ans;
    13. static {
    14. for (int i = 0; i < node.length; i++) {
    15. node[i] = new Node();
    16. }
    17. }
    18. static void initHash() {
    19. for (int i = 0; i < H; i++)
    20. hashTable[i] = -1;
    21. cur = 0;
    22. ans = 0;
    23. }
    24. static void insertHash(int x, int y) {
    25. int h = (x * x + y * y) % H;
    26. node[cur].x = x;
    27. node[cur].y = y;
    28. node[cur].next = hashTable[h];
    29. hashTable[h] = cur++;
    30. }
    31. static boolean searchHash(int x, int y) {
    32. int h = (x * x + y * y) % H;
    33. int next = hashTable[h];
    34. while (next != -1) {
    35. if (x == node[next].x && y == node[next].y)
    36. return true;
    37. next = node[next].next;
    38. }
    39. return false;
    40. }
    41. public static void main(String[] args) {
    42. int xx, yy, x1, y1, x2, y2;
    43. while (true) {
    44. Scanner scanner = new Scanner(System.in);
    45. n = scanner.nextInt();
    46. if (n == 0) {
    47. return;
    48. }
    49. initHash();
    50. for (int i = 0; i < n; i++) {
    51. sx[i] = scanner.nextInt();
    52. sy[i] = scanner.nextInt();
    53. insertHash(sx[i], sy[i]);
    54. }
    55. for (int i = 0; i < n; i++) {
    56. for (int j = i + 1; j < n; j++) {
    57. xx = sx[i] - sx[j];
    58. yy = sy[i] - sy[j];
    59. x1 = sx[i] - yy;
    60. y1 = sy[i] + xx;
    61. x2 = sx[j] - yy;
    62. y2 = sy[j] + xx;
    63. if (searchHash(x1, y1) && searchHash(x2, y2))
    64. ans++;
    65. x1 = sx[i] + yy;
    66. y1 = sy[i] - xx;
    67. x2 = sx[j] + yy;
    68. y2 = sy[j] - xx;
    69. if (searchHash(x1, y1) && searchHash(x2, y2))
    70. ans++;
    71. }
    72. }
    73. System.out.println(ans >>= 2);
    74. }
    75. }
    76. }
    77. class Node {
    78. int x;
    79. int y;
    80. int next;
    81. }

    七 测试

    绿色为输入,白色为输出

  • 相关阅读:
    【MKS_GEN_L 主板使用说明书】
    16. Docker容器监控CAdvisor+InfluxDB+Granfana
    2024年FPGA可以进吗
    【软件逆向-基础知识】分析方法、汇编指令体系结构
    树形结构 一篇文章梳理
    Python中的元类(metaclass)
    Dynamsoft Dynamic .NET TWAIN for net Crack
    Android 模拟点击
    信息学奥赛一本通 1915:【01NOIP普及组】最大公约数与最小公倍数 | 洛谷 P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题
    看知名企业们如何利用 Web3进行产业重塑
  • 原文地址:https://blog.csdn.net/chengqiuming/article/details/126082522