結果
問題 | No.202 1円玉投げ |
ユーザー | Kilisame |
提出日時 | 2016-06-10 16:12:52 |
言語 | Java21 (openjdk 21) |
結果 |
WA
|
実行時間 | - |
コード長 | 6,861 bytes |
コンパイル時間 | 3,023 ms |
コンパイル使用メモリ | 80,492 KB |
実行使用メモリ | 75,864 KB |
最終ジャッジ日時 | 2024-12-22 10:26:14 |
合計ジャッジ時間 | 31,530 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | WA | - |
testcase_01 | WA | - |
testcase_02 | WA | - |
testcase_03 | WA | - |
testcase_04 | WA | - |
testcase_05 | WA | - |
testcase_06 | WA | - |
testcase_07 | WA | - |
testcase_08 | WA | - |
testcase_09 | WA | - |
testcase_10 | WA | - |
testcase_11 | WA | - |
testcase_12 | WA | - |
testcase_13 | WA | - |
testcase_14 | WA | - |
testcase_15 | WA | - |
testcase_16 | WA | - |
testcase_17 | WA | - |
testcase_18 | WA | - |
testcase_19 | WA | - |
testcase_20 | WA | - |
testcase_21 | WA | - |
testcase_22 | WA | - |
testcase_23 | WA | - |
testcase_24 | WA | - |
testcase_25 | WA | - |
testcase_26 | WA | - |
testcase_27 | WA | - |
testcase_28 | WA | - |
testcase_29 | WA | - |
testcase_30 | WA | - |
testcase_31 | WA | - |
testcase_32 | WA | - |
testcase_33 | WA | - |
testcase_34 | WA | - |
testcase_35 | WA | - |
testcase_36 | WA | - |
testcase_37 | WA | - |
testcase_38 | WA | - |
testcase_39 | WA | - |
testcase_40 | WA | - |
ソースコード
import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Scanner; import java.util.Set; public class Main { private static final int BLOCK_SIZE = 200; private static Set<Point>[][] leftOfCoinSet = new Set[20000 / BLOCK_SIZE + 1][20000 / BLOCK_SIZE + 1]; public static void main(String[] args) { Scanner cin = new Scanner(System.in); int limit = cin.nextInt(); int leftCount = 0; long begin = System.currentTimeMillis(); for (int i = 0; i < limit; i++) { int x = cin.nextInt(); int y = cin.nextInt(); /* x,yそれぞれ1/200して、200*200の範囲内で干渉しあう円の中心情報を得る */ if (isLeft(x, y)) { leftCount++; } } long end = System.currentTimeMillis(); System.out.println(leftCount); System.out.println("execute=" + (end - begin)); } private static boolean isLeft(int x, int y) { Point thisCoin = new Point(x, y); /* 落ちたコインの中心座標からブロックを求める */ int blockX = x / BLOCK_SIZE; int blockY = y / BLOCK_SIZE; /* どのブロックにまたがっているか。順に左、右、下、上、左下、右下、左上、右上で8要素配列 */ boolean[] isStradding = new boolean[4]; List<Set<Point>> checkPointList = new ArrayList<Set<Point>>(); if (leftOfCoinSet[blockX][blockY] == null) { leftOfCoinSet[blockX][blockY] = new HashSet<Point>(); } checkPointList.add(leftOfCoinSet[blockX][blockY]); if (blockX > 0 && x % BLOCK_SIZE < 10) { /* 左チェック。左端以外のBlockでかつ、x座標をBLOCK_SIZEで割った時の余りが半径の10に満たない場合 */ isStradding[0] = true; if (leftOfCoinSet[blockX - 1][blockY] == null) { leftOfCoinSet[blockX - 1][blockY] = new HashSet<Point>(); } checkPointList.add(leftOfCoinSet[blockX - 1][blockY]); } else if (blockX < 20000 / BLOCK_SIZE && x % BLOCK_SIZE >= BLOCK_SIZE - 10) { /* 右チェック。右端以外のBlockでかつ、x座標をBLOCK_SIZEで割った時の余りがBLOCK_SIZEから半径の10を引いた値以上になる場合 */ isStradding[1] = true; if (leftOfCoinSet[blockX + 1][blockY] == null) { leftOfCoinSet[blockX + 1][blockY] = new HashSet<Point>(); } checkPointList.add(leftOfCoinSet[blockX + 1][blockY]); } if (blockY > 0 && y % BLOCK_SIZE < 10) { /* 下チェック。下端以外のBlockでかつ、y座標をBLOCK_SIZEで割った時の余りが半径の10に満たない場合 */ isStradding[2] = true; if (leftOfCoinSet[blockX][blockY - 1] == null) { leftOfCoinSet[blockX][blockY - 1] = new HashSet<Point>(); } checkPointList.add(leftOfCoinSet[blockX][blockY - 1]); } else if (blockY < 20000 / BLOCK_SIZE && y % BLOCK_SIZE >= BLOCK_SIZE - 10) { /* 右チェック。右端以外のBlockでかつ、x座標をBLOCK_SIZEで割った時の余りがBLOCK_SIZEから半径の10を引いた値以上になる場合 */ isStradding[3] = true; if (leftOfCoinSet[blockX][blockY + 1] == null) { leftOfCoinSet[blockX][blockY + 1] = new HashSet<Point>(); } checkPointList.add(leftOfCoinSet[blockX][blockY + 1]); } if (isStradding[0] && isStradding[2]) { /* 左と下両方にはみ出ている場合のみ、追加で左下ブロックを判定 */ if (thisCoin.getDistance(blockX * BLOCK_SIZE - 1, blockY * BLOCK_SIZE - 1) < 100) { if (leftOfCoinSet[blockX - 1][blockY - 1] == null) { leftOfCoinSet[blockX - 1][blockY - 1] = new HashSet<Point>(); } checkPointList.add(leftOfCoinSet[blockX - 1][blockY - 1]); } } else if (isStradding[0] && isStradding[3]) { /* 左と上両方にはみ出ている場合のみ、追加で左上ブロックを判定 */ if (thisCoin.getDistance(blockX * BLOCK_SIZE - 1, (blockY + 1) * BLOCK_SIZE) < 100) { if (leftOfCoinSet[blockX - 1][blockY + 1] == null) { leftOfCoinSet[blockX - 1][blockY + 1] = new HashSet<Point>(); } checkPointList.add(leftOfCoinSet[blockX - 1][blockY + 1]); } } else if (isStradding[1] && isStradding[2]) { /* 右と下両方にはみ出ている場合のみ、追加で右下ブロックを判定 */ if (thisCoin.getDistance((blockX + 1) * BLOCK_SIZE, blockY * BLOCK_SIZE - 1) < 100) { if (leftOfCoinSet[blockX + 1][blockY - 1] == null) { leftOfCoinSet[blockX + 1][blockY - 1] = new HashSet<Point>(); } checkPointList.add(leftOfCoinSet[blockX + 1][blockY - 1]); } } else if (isStradding[1] && isStradding[3]) { /* 右と上両方にはみ出ている場合のみ、追加で右上ブロックを判定 */ if (thisCoin.getDistance((blockX + 1) * BLOCK_SIZE, (blockY + 1) * BLOCK_SIZE) < 100) { if (leftOfCoinSet[blockX + 1][blockY + 1] == null) { leftOfCoinSet[blockX + 1][blockY + 1] = new HashSet<Point>(); } checkPointList.add(leftOfCoinSet[blockX + 1][blockY + 1]); } } return checkDistance(thisCoin, checkPointList); } private static boolean checkDistance(Point point, List<Set<Point>> leftCoinSetList) { for (Set<Point> leftCoinSet : leftCoinSetList) { for (Point leftPoint : leftCoinSet) { if (leftPoint.getDistance(point) < 400) { return false; } } } for (Set<Point> leftCoinSet : leftCoinSetList) { leftCoinSet.add(point); } /* 全てチェックOKならば、チェックした対象のSetに対して自分自身を追加する */ return true; } static class Point { int x; int y; Point(int x, int y) { this.x = x; this.y = y; } public boolean equals(Point other) { return x == other.x && y == other.y; } public int getDistance(int otherX, int otherY) { return (x - otherX) * (x - otherX) + (y - otherY) * (y - otherY); } public int getDistance(Point other) { return (x - other.x) * (x - other.x) + (y - other.y) * (y - other.y); } } }