로고는 주로 교육용에 쓰이는 프로그래밍 언어이다. 로고의 가장 큰 특징은 거북이 로봇인데, 사용자는 이 거북이 로봇을 움직이는 명령을 입력해 화면에 도형을 그릴 수 있다.
거북이는 위치와 각도로 표현할 수 있다. 거북이는 입에 연필을 물고 있는데, 연필을 내리면 움직일 때 화면에 선을 그리고, 올리면 선을 그리지 않고 그냥 지나가기만 한다.
제일 처음에 거북이는 (0,0)에 있고, 거북이가 보고 있는 방향은 y축이 증가하는 방향이다. 또한 연필은 내리고 있다.
사용자는 다음과 같은 다섯가지 명령으로 거북이를 조정할 수 있다.
축에 평행한 직사각형 N개가 주어졌을 때, 이 직사각형을 그리는데 필요한 PU 명령의 최솟값을 구하는 프로그램을 작성하시오.
거북이는 같은 선을 여러 번 그릴 수 있지만, 문제에 주어진 직사각형 N개를 제외한 직사각형을 그릴 수 없다. 거북이의 크기는 아주 작아서 좌표 평면의 한 점이라고 생각하면 된다. 직사각형의 변은 축에 평행하다.
첫째 줄에 직사각형의 개수 N이 주어진다. (1 ≤ N ≤ 1000)
다음 N개의 줄에는 직사각형의 좌표 x1, y1, x2, y2가 주어진다. (−500 ≤ x1 < x2 ≤ 500), (−500 ≤ y1 < y2 ≤ 500) (x1, y1)는 직사각형의 한 꼭짓점 좌표이고, (x2, y2)는 그 점의 대각선 방향의 반대 꼭짓점의 좌표이다.
N개의 직사각형을 그리는 필요한 PU명령의 최솟값을 출력한다.
5
1 1 4 4
3 3 6 6
4 4 5 5
5 0 8 3
6 1 7 2
2
이 문제는 한붓그리기가 가능한 그룹을 나눠서 몇번 그리면 되는 지를 체크하면 풀 수 있는 문제이다. DFS 알고리즘을 이용해서 풀었다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N;
static Rect[] arr;
static boolean[] visited;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
arr = new Rect[N];
visited = new boolean[N];
int cnt = 0;
boolean isZero = false;
for(int i=0; i<N; i++) {
String[] input = br.readLine().split(" ");
int x1 = Integer.parseInt(input[0]);
int y1 = Integer.parseInt(input[1]);
int x2 = Integer.parseInt(input[2]);
int y2 = Integer.parseInt(input[3]);
arr[i] = new Rect(x1, y1, x2, y2);
if((x2==0 && (y1<=0 && y2>=0)) || (x1==0 && (y1<=0 && y2>=0))) isZero = true;
}
if(isZero) cnt--;
for(int i=0; i<N; i++) {
if(!visited[i]) {
visited[i] = true;
dfs(i);
cnt++;
}
}
System.out.println(cnt);
}
public static void dfs(int idx) {
for(int i=0; i<N; i++) {
if(check(arr[i], arr[idx]) && !visited[i]) {
visited[i] = true;
dfs(i);
}
}
}
public static boolean check(Rect rec1, Rect rec2) {
if (rec1.x1 > rec2.x1 && rec1.y1 > rec2.y1 && rec1.x2 < rec2.x2 && rec1.y2 < rec2.y2)
return false;
if (rec1.x1 < rec2.x1 && rec1.y1 < rec2.y1 && rec1.x2 > rec2.x2 && rec1.y2 > rec2.y2)
return false;
return rec1.x1 <= rec2.x2 && rec1.y1 <= rec2.y2 && rec2.x1 <= rec1.x2 && rec2.y1 <= rec1.y2;
}
public static class Rect {
int x1;
int y1;
int x2;
int y2;
public Rect(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
}
}