https://www.hackerrank.com/challenges/gridland-metro/problem
분류 : Search
문제 설명
n x m 으로 나타낼 수 있는 Gridland 에는 수평 방향의 철길들이 있다.
즉 각각의 철길은 (r, c1, c2) 로 나타낼 수 있다. r 은 row , c1 은 start 지점, c2 는 end 지점을 나타낸다.
철길이 있는 곳을 제외하고 lampost 들을 설치하려고 하는데, 설치할 수 있는 lampost 의 개수는 ?
Input 예시
첫 줄에는 n, m, k 가 주어진다. k 는 철길의 개수다.
다음에는 k 개의 철길 정보가 주어진다. 철길 정보는 r , c1, c2 순으로 입력된다.
1 <= n, m <= 10 ^9 임을 유의하자.
같은 행에 여러개의 철길이 있을 수 있고, 겹쳐 있을 수도 있다..
입력의 자세한 예시와 결과는 위에 링크를 참고하도록 하자. 예시가 잘 나와 있다.
풀이
n x m 의 범위가 int 를 넘기 때문에 정답도 당연히 int 의 범위를 넘을 수 있다.
이것때문에 계속 틀렸다.ㅠㅠ
정답을 저장하는 변수를 long long 으로 선언해줘야 한다. (long long 은 64bit -> 10^18 까지 커버 가능)
풀이 과정은 대략 다음과 같다.
n x m 한 값을 먼저 ans 변수에 담고, 기차가 차지하는 면적을 빼주는 식으로 구현했다.
- 먼저 입력을 row 순으로 오름 차순 정렬한다.
- 같은 row 인 기차 정보들끼리 있을 수 있도록 vector 에 담는다.
ex) (1,1,3) (2,1,2) , (1,2,4) 이렇게 input 이 들어오면 vector[0] = [(1,3),(2,4) ], vector[1] = [(1,2)] 이런 식으로
여기선 trains 라는 vector 자료형에 담았다. trains 는 pair 로 이루어진 vector 를 담는다.
using train = vector<pair<int,int>>;
vector<train> trains; //store train's start, end point in row
for(vector<int>& info : track) {
if(info[0] != cur_row) {
trains.emplace_back();
cur_row = info[0];
}
(*(trains.end()-1)).emplace_back(info[1], info[2]);
}
3. 각 row 정보를 돌면서 기차가 차지하고 있는 칸의 개수를 센다. 겹쳐있는 기차는 합친다고 생각하면 된다.
3의 과정이 이 문제의 핵심 알고리즘이다.
기차가 겹쳐있을 수 있기 때문에, 이를 고려해야 한다. 나는 discussion 을 참고해 stack 을 사용했다.
- stack 에 row 의 제일 첫번째 기찻길 정보를 넣는다.
- row 에 있는 기찻길을 순회하면서 다음의 과정을 반복한다.
2-1. 현재 기찻길의 시작점이 stack top 에있는 기찻길의 시작점과 끝점 사이에 있는 점이라면
2-2. 해당 점의 끝점이 stack top 에 있는 끝점보다 크다면 끝점을 갱신해준다.
2-3. 2-1 에 해당하지 않는다면, 해당 정보를 stack 에 넣는다. - stack 에 있는 기찻길 정보를 돌면서 ans 를 갱신한다.
전체 코드
#include<iostream>
#include <vector>
#include <algorithm> //sort
#include <stack>
using namespace std;
using train = vector<pair<int,int>>;
// Complete the gridlandMetro function below.
long long gridlandMetro(int n, int m, int k, vector<vector<int>> &track) { // row c1 c2
long long ans = ((long long)n)*((long long)m); //10^18
auto comp = [](vector<int> &a,vector<int> &b){
if(a[0] == b[0]){
if(a[1] == b[1])
return a[2] < b[2];
else
return a[1] < b[1];
} else {
return a[0] < b[0];
}
};
sort(track.begin(), track.end(),comp);
vector<train> trains; //store train's start, end point in row
int cur_row = 0;
for(vector<int>& info : track) {
if(info[0] != cur_row) {
trains.emplace_back();
cur_row = info[0];
}
(*(trains.end()-1)).emplace_back(info[1], info[2]);
}
for(train &t : trains) {
stack<pair<int,int>> temp;
temp.emplace(move(t[0]));
int s = t.size();
for(int i=1; i<s; i++) { // (1,5) | (1,2) (1,3) (2,3) (5,5)
if( (t[i].first >= temp.top().first) && (t[i].first <= temp.top().second) ) {
if(t[i].second > temp.top().second) {
temp.top().second = t[i].second;
}
} else {
temp.emplace(move(t[i])); //해당안 되면 stack 에 push
}
}
while(!temp.empty()) {
ans-= (temp.top().second - temp.top().first + 1);
temp.pop();
}
}
return ans;
}
int main() {
int n,m,k;
cin >> n >> m >> k;
vector<vector<int>> input(k);
for(int i=0; i<k; i++) {
int a,b,c;
cin >> a >> b >> c;
input[i] = {a,b,c};
}
cout << gridlandMetro(n,m,k,input) << "\n";
}
'Algorithm > 기타사이트' 카테고리의 다른 글
프로그래머스 - 타겟 넘버 (0) | 2021.11.24 |
---|---|
위장 (0) | 2021.04.05 |
Lily's Homework (0) | 2020.07.27 |
[Hackerrank] - Maximum Palindromes (0) | 2020.07.18 |