11758번 - CCW
문제 풀이 시간 : 1시간
문제 설명
- 3 점 P1, P2, P3가 주어진다.
- P1, P2, P3를 순서대로 이은 선분이 반시계 방향을 나타내면 1
- 시계방향이면 -1
- 일직선이면 0 을 출력한다.
문제 풀이
처음에는 이 문제를 보고 기울기를 활용해서 푸는거 아닌가?
라는 생각으로 접근했다.
첫번째 선분의 기울기보다 두번째 선분의 기울기가 더 작으면 시계방향,
아니라면 반시계 방향으로 생각을하고 코드를 짰다.
초기 코드
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;
private final int b;
Point(int a, int b) {
this.a = a;
this.b = b;
}
}
public static Point[] arr =new Point[3];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
for (int i = 0; i < 3; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
arr[i] = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
}
int a = (arr[1].b - arr[0].b) / (arr[1].a - arr[0].a);
int b = (arr[2].b - arr[1].b) / (arr[2].a - arr[1].a);
if (a > b) {
System.out.println(-1);
} else if (a < b) {
System.out.println(1);
}
else
System.out.println(0);
}
}
근데 틀렸다.
너무 단순하게 생각했던 것 같다.
조금만 더 생각을 해보면 이 문제는 단순히 기울기로는 풀 수 없는 문제인 것이다.
도저히 모르겠어서 문제의 제목인 CCW를 검색해 보았다.
CCW는 Counter-ClockWise 의 줄임말이다.
이 알고리즘은 평면상의 3개의 점의 위치관계를 판단하는 알고리즘이다.
일직선

반시계 방향
위와 같이 3가지 경우를 판단할 때 쓰이는 알고리즘이다.
식을 설명하자면
이렇게 된다.
이 식이 나오게 된 방법은 문제를 풀 때 크게 중요하지 않은 부분이기 때문에 넘어가도록 하겠다.
위 식을 이해하기 쉽게 그림으로 나타낸다면 아래와 같다.

여기서 검은 선은 곱하고 더하기, 붉은 선은 곱하고 빼주면 된다.
이렇게 나온 결과가 0보다 작다면 시계방향, 0과 같다면 일직선, 0보다 크다면 반시계 방향을 나타내게 된다.
이 알고리즘을 활용해서 문제를 풀어보면 아주 쉽게 풀 수 있다.
정답 코드
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[4];
for (int i = 0; i < 3; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
arr[i] = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
}
arr[3] = arr[0];
int d = 0;
for (int i = 0; i < 3; i++) {
d += arr[i].a * arr[i + 1].b;
}
for (int i = 1; i <= 3; i++) {
d -= arr[i].a * arr[i - 1].b;
}
if (d < 0) {
System.out.println(-1);
} else if (d > 0) {
System.out.println(1);
} else {
System.out.println(0);
}
}
}
함께 읽으면 좋은 글
5430번 - AC
함수 R은 배열을 뒤집는 연산 함수 D는 첫 번째 원소를 버리는 연산 단, 배열이 비어 있을 때 D를 수행하면 error 주어진 함수 문자열을 순서대로 수행한 뒤 최종 배열을 출력하는 문제 처음에는 문제 설명 그대로 R이 나올 때마다 배열을 실제로 뒤집고, D가 나오면 맨 앞…
1966번 - 프린터 큐
여러 문서가 큐에 들어 있고, 각 문서마다 중요도가 있음 맨 앞 문서를 확인했을 때, 더 높은 중요도의 문서가 뒤에 하나라도 있으면 맨 뒤로 보냄 그렇지 않으면 바로 인쇄 특정 위치의 문서가 몇 번째로 인쇄되는지 구하는 문제 이 문제는 프린터의 동작을 그대로 구현하면 되는…
1158 - 요세푸스 문제
1번부터 N번까지 사람이 원형으로 앉아 있음 순서대로 K번째 사람을 제거 모든 사람이 제거될 때까지 반복 제거되는 순서를 출력하는 문제 이 문제는 원형으로 순회하면서 K번째를 제거하는 과정을 그대로 구현하면 된다.
2164번 - 카드2
1부터 N까지 카드가 순서대로 쌓여 있음 맨 위 카드를 버리고, 그다음 맨 위 카드를 맨 아래로 옮기는 과정을 반복 마지막에 남는 카드 번호를 구하는 문제 이 문제는 규칙을 찾기보다, 문제에서 하라는 과정을 그대로 구현하면 된다. 카드 더미에서 반복되는 동작은 두 가지다.