백준 #11651 / 좌표 정렬하기 2
문제
2차원 평면 위의 점 N개가 주어진다. 좌표를 y좌표가 증가하는 순으로, y좌표가 같으면 x좌표가 증가하는 순서로 정렬한 다음 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 점의 개수 N (1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N개의 줄에는 i번점의 위치 xi와 yi가 주어진다. (-100,000 ≤ xi, yi ≤ 100,000) 좌표는 항상 정수이고, 위치가 같은 두 점은 없다.
출력
첫째 줄부터 N개의 줄에 점을 정렬한 결과를 출력한다.
단순한 문제지만, STL의 sort 특징을 알게되어서 포스팅해본다.
우선, 나는 MergeSort로 하나 하나 코딩했다.
[How To Solve?]
- N * 2 크기의 2차원 배열 생성
- N행 0열에는 x좌표, 1열에는 y좌표를 저장한다.
- mergeSort를 이용하여, y좌표가 같은경우와 같지 않은 경우로 나눈다.
- 같은 경우, x좌표의 대소 비교를 또 조건에 넣어 다뤄준다.
[Code]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | #include<iostream> using namespace std; void mergeSort(int, int, int**); void merge(int, int, int, int**); int **result; int main() { ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); int N; cin >> N; int **arr = new int*[N]; result = new int*[N]; for (int i = 0; i < N; i++) { arr[i] = new int[2]; result[i] = new int[2]; } for (int i = 0; i < N; i++) cin >> arr[i][0] >> arr[i][1]; mergeSort(0, N - 1, arr); for (int i = 0; i < N; i++) printf("%d %d\n", result[i][0], result[i][1]); return 0; } void mergeSort(int left, int right, int **arr) { int mid; // 가운데 인덱스 if (left < right) { // left가 right와 같아지는 순간 정렬 끝. mid = (left + right) / 2; mergeSort(left, mid, arr); mergeSort(mid+1, right, arr); merge(left, mid, right, arr); } } void merge(int left, int mid, int right, int **arr) { int l = left; int m = mid + 1; int k = left; while (l <= mid || m <= right) { if (l<= mid && m <= right) { // 비교해야할 배열이 쪼개진 배열 둘 다 남아있는 경우 if (arr[l][1] == arr[m][1]) // y좌표가 같은 경우 { if (arr[l][0] <= arr[m][0]) { // m의 x좌표가 더 크거나 같은경우 result[k][0] = arr[l][0]; result[k][1] = arr[l++][1]; } else // l의 x좌표가 더 큰 경우 { result[k][0] = arr[m][0]; result[k][1] = arr[m++][1]; } } else if (arr[l][1] > arr[m][1]) { // l의 y좌표가 m의 y좌표보다 큰 경우 result[k][0] = arr[m][0]; result[k][1] = arr[m++][1]; } else { result[k][0] = arr[l][0]; result[k][1] = arr[l++][1]; } } else if (l <= mid && m > right) { // l에만 남아있음 result[k][0] = arr[l][0]; result[k][1] = arr[l++][1]; } else { result[k][0] = arr[m][0]; result[k][1] = arr[m++][1]; } k++; } for (int i = left; i < right + 1; i++) { arr[i][0] = result[i][0]; arr[i][1] = result[i][1]; } } | cs |
// 주석
- 실행시간이 68MS... 1등은 32MS
- 무슨 차이인가 싶어서 1등 코드를 봤으나 이해불가... 2등인 40MS로 넘어가서 확인해본 결과, STL의 sort를 사용했다.
// 뭘 알게 되었는가?
- pair로 짝을 만들어놓는다. 예를 들어, xy좌표평면이라면 pair<int,int>
- 궁금해서 3차원 공간좌표로 바꿔서 pair<int, pair<int, int> >로 바꿨다.
- sort를 사용하게 되면, pair의 경우 first부터 차례대로 정렬된다.
- 무슨 말이냐면, pair는 first와 second를 갖고 있지 않은가?
- 입력을 거꾸로 second first로 받으면 y좌표가 x로 들어가고 x좌표가 y로 들어가게 된다.
- 결국에는 y좌표를 정렬한 후 x좌표를 정렬한다는 것.
- 출력할 때에는 입력받은 순서대로 그대로 출력하면 된다.
[Code]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <iostream> #include <algorithm> using namespace std; pair<int, pair<int, int> > Input[100005]; int N; int main() { //freopen("input.txt", "r", stdin); cin.sync_with_stdio(false); cin >> N; int x, y; for (int i = 0; i < N; i++) cin >> Input[i].second.first >> Input[i].first >> Input[i].second.second; sort(Input, Input + N); for (int i = 0; i < N; i++) printf("%d %d %d\n", Input[i].first, Input[i].second.first, Input[i].second.second); } | cs |
// 추가
- 그렇다면, 2차원 배열로도 가능할까?
- 이건 나중에... 잘 모르겠다 만약 STL을 쓸 수 없는 경우에는 mergeSort를 이용하는 것이 편할듯 싶다.