12781 - PIZZA ALVOLOC
문제 풀이 시간 : 1시간
문제 설명:
- 도윤이는 친구 3명과 함께 피자를 나눠 먹는다.
- 피자는 항상 볼록 다각형이다.
- 피자를 네등분해서 나눠 먹는다.
- 나누어진 피자가 4조각이 되는지 판단하자.

문제 풀이:
이 문제는 저번 시간에 발표했던 CCW를 활용하는 문제이다.
이왕 CCW를 알아본 김에 활용문제를 좀 풀어보면서 어떤식으로 쓰이는지 알아보고자 풀게되었다.
다들 CCW의 공식은 기억하겠지..?
나는 처음 이 문제를 보자마자 아래와 같이 두 점을 기준으로 나머지 두 점과의 위치 관계를 CCW로 판단하여
두 선의 방향이 반대라면 4조각으로 나누어지는 것이 아닌가? 라는 생각으로 문제를 풀었다.

코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static class Point {
private final int a, b;
Point(int a, int b) {
this.a = a;
this.b = b;
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Point[] arr = new Point[5];
Point[] arr1 = new Point[4];
Point[] arr2 = new Point[4];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < 4; i++) {
arr[i] = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
}
for (int i = 0; i < 2; i++) {
arr1[i] = arr2[i] = arr[i];
}
arr1[2] = arr[2];
arr2[2] = arr[3];
arr1[3] = arr2[3] = arr[0];
int d1 = 0, d2 = 0;
for (int i = 0; i < 3; i++) {
d1 += arr1[i].a * arr1[i + 1].b;
d2 += arr2[i].a * arr2[i + 1].b;
}
for (int i = 1; i <= 3; i++) {
d1 -= arr1[i].a * arr1[i - 1].b;
d2 -= arr2[i].a * arr2[i - 1].b;
}
if (d1 * d2 < 0) {
System.out.println(1);
} else {
System.out.println(0);
}
}
}
위와 같이 코드를 짰더니 1%에서 틀렸다가 나온다.
왜 그럴까?
아무리 생각해도 문제점이 보이지 않았다.
그래서 결국 검색 찬스를 쓰게 되었다.
나는 그냥 예시 사진만 보고 정다각형이라고 생각한 것이다.
근데 문제에서는 볼록 다각형이라고 주어졌다.
즉, 피자의 모양은 얼마든지 기괴해질 수 있다는 것이다.
아래와 같은 상황을 보자.

실제로는 이런 상황은 없겠지만 극단적인 예이다.
위의 예시를 봤을 때, A,B를 기준으로 C,D를 판단했을 때는 두 선이 반대 방향이므로 CCW를 만족하는 것처럼 보인다.
하지만, C,D를 기준으로 A,B를 본다면 두 선이 같은 방향이 된다.
따라서 이 4점은 교차하지 않는다는 것을 알 수 있다.
이렇게 CCW를 이용해서 선분의 교차 여부를 판단하고자 한다면 다른 두 점을 사용해서 모든 경우를 판단해봐야 한다고 한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static class Point {
private final int a, b;
Point(int a, int b) {
this.a = a;
this.b = b;
}
}
public static int ccw(Point p1, Point p2, Point p3) {
int d = p1.a * p2.b + p2.a * p3.b + p3.a * p1.b;
d -= p2.a * p1.b + p3.a * p2.b + p1.a * p3.b;
if (d > 0) return 1;
else if (d < 0) return -1;
else return 0;
}
public static boolean isPossible(int d1, int d2) {
return d1 * d2 < 0;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Point[] arr = new Point[4];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < 4; i++) {
arr[i] = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
}
if (isPossible(ccw(arr[0], arr[1], arr[2]), ccw(arr[0], arr[1], arr[3]))) {
if (isPossible(ccw(arr[2], arr[3], arr[0]), ccw(arr[2], arr[3], arr[1]))) {
System.out.println(1);
return;
}
}
System.out.println(0);
}
}
함께 읽으면 좋은 글
5430번 - AC
함수 R은 배열을 뒤집는 연산 함수 D는 첫 번째 원소를 버리는 연산 단, 배열이 비어 있을 때 D를 수행하면 error 주어진 함수 문자열을 순서대로 수행한 뒤 최종 배열을 출력하는 문제 처음에는 문제 설명 그대로 R이 나올 때마다 배열을 실제로 뒤집고, D가 나오면 맨 앞…
1966번 - 프린터 큐
여러 문서가 큐에 들어 있고, 각 문서마다 중요도가 있음 맨 앞 문서를 확인했을 때, 더 높은 중요도의 문서가 뒤에 하나라도 있으면 맨 뒤로 보냄 그렇지 않으면 바로 인쇄 특정 위치의 문서가 몇 번째로 인쇄되는지 구하는 문제 이 문제는 프린터의 동작을 그대로 구현하면 되는…
1158 - 요세푸스 문제
1번부터 N번까지 사람이 원형으로 앉아 있음 순서대로 K번째 사람을 제거 모든 사람이 제거될 때까지 반복 제거되는 순서를 출력하는 문제 이 문제는 원형으로 순회하면서 K번째를 제거하는 과정을 그대로 구현하면 된다.
2164번 - 카드2
1부터 N까지 카드가 순서대로 쌓여 있음 맨 위 카드를 버리고, 그다음 맨 위 카드를 맨 아래로 옮기는 과정을 반복 마지막에 남는 카드 번호를 구하는 문제 이 문제는 규칙을 찾기보다, 문제에서 하라는 과정을 그대로 구현하면 된다. 카드 더미에서 반복되는 동작은 두 가지다.