Last active
June 11, 2022 21:04
-
-
Save korobochka/aac5c2561ef5b9accf6bf2a68b7b177d to your computer and use it in GitHub Desktop.
Queen's Attack II
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.*; | |
import java.math.*; | |
import java.security.*; | |
import java.text.*; | |
import java.util.*; | |
import java.util.concurrent.*; | |
import java.util.function.*; | |
import java.util.regex.*; | |
import java.util.stream.*; | |
import static java.util.stream.Collectors.joining; | |
import static java.util.stream.Collectors.toList; | |
class Point { | |
public final int row; | |
public final int col; | |
Point(int r, int c) { this.row = r; this.col = c; } | |
public int distance(Point other) { | |
return Math.max(Math.abs(row - other.row), Math.abs(col - other.col)); | |
} | |
public boolean directionUpRight(Point other) { | |
if (row == other.row) return other.col > col; | |
return other.row > row; | |
} | |
} | |
class Line { | |
// a * col + b * row + c == 0 | |
int a; int b; int c; | |
Point through; | |
public Line(int a, int b, Point through) { | |
this.a = a; this.b = b; | |
this.through = through; | |
this.c = - a * through.col - b * through.row; | |
} | |
private int distPositive = Integer.MAX_VALUE; | |
private int distNegative = Integer.MAX_VALUE; | |
public void addObstacle(Point other) { | |
int distance = through.distance(other) -1; | |
if (through.directionUpRight(other)) { | |
if (distance < distPositive) { | |
distPositive = distance; | |
} | |
} | |
else { | |
if (distance < distNegative) { | |
distNegative = distance; | |
} | |
} | |
} | |
public boolean pointOnLine(Point point) { | |
return a * point.col + b * point.row + c == 0; | |
} | |
public Point intersection(Line other) { | |
// (x, y) = ((b1*c2-b2*c1)/(a1*b2-a2*b1), (c1*a2-c2*a1)/(a1*b2-a2*b1)) | |
int d = a * other.b - other.a * b; | |
if (d == 0) return null; | |
return new Point( | |
(c * other.a - other.c * a) / d, | |
(b * other.c - other.b * c) / d | |
); | |
} | |
public int getLength(int n) { | |
List<Line> box = new ArrayList<>(); | |
box.add(new Line(1, 0, new Point(0, 0))); // left | |
box.add(new Line(1, 0, new Point(0, n + 1))); // right | |
box.add(new Line(0, 1, new Point(0, 0))); // bottom | |
box.add(new Line(0, 1, new Point(n + 1, 0))); // top | |
List<Point> intersections = box.stream().map(l -> l.intersection(this)).collect(Collectors.toList()); | |
for(Point intersection : intersections) { | |
if (intersection == null) continue; | |
this.addObstacle(intersection); | |
} | |
return distPositive + distNegative; | |
} | |
} | |
class Result { | |
public static int queensAttack(int n, int k, int r_q, int c_q, List<List<Integer>> obstacles) { | |
Point queen = new Point(r_q, c_q); | |
List<Line> lines = new ArrayList<>(); | |
lines.add(new Line(0, 1, queen)); // horizontal | |
lines.add(new Line(1, 0, queen)); // vertical | |
lines.add(new Line(-1, 1, queen)); // diagonal / | |
lines.add(new Line(1, 1, queen)); // diagonal \ | |
for (List<Integer> coords : obstacles) { | |
Point obstacle = new Point(coords.get(0), coords.get(1)); | |
for (Line line : lines) { | |
if (line.pointOnLine(obstacle)) { | |
line.addObstacle(obstacle); | |
} | |
} | |
} | |
return lines.stream().mapToInt(l -> l.getLength(n)).sum(); | |
} | |
} | |
public class Solution { | |
public static void main(String[] args) throws IOException { | |
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); | |
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH"))); | |
String[] firstMultipleInput = bufferedReader.readLine().replaceAll("\\s+$", "").split(" "); | |
int n = Integer.parseInt(firstMultipleInput[0]); | |
int k = Integer.parseInt(firstMultipleInput[1]); | |
String[] secondMultipleInput = bufferedReader.readLine().replaceAll("\\s+$", "").split(" "); | |
int r_q = Integer.parseInt(secondMultipleInput[0]); | |
int c_q = Integer.parseInt(secondMultipleInput[1]); | |
List<List<Integer>> obstacles = new ArrayList<>(); | |
IntStream.range(0, k).forEach(i -> { | |
try { | |
obstacles.add( | |
Stream.of(bufferedReader.readLine().replaceAll("\\s+$", "").split(" ")) | |
.map(Integer::parseInt) | |
.collect(toList()) | |
); | |
} catch (IOException ex) { | |
throw new RuntimeException(ex); | |
} | |
}); | |
int result = Result.queensAttack(n, k, r_q, c_q, obstacles); | |
bufferedWriter.write(String.valueOf(result)); | |
bufferedWriter.newLine(); | |
bufferedReader.close(); | |
bufferedWriter.close(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment