풀이 방법

 

이 문제는 두 지점 사이의 최소 거울 수를 구하는 문제로, 평소 두 지점의 최단거리를 구할 때 사용하는 BFS 를 응용해 "거리" 대신 "거울 수(방향 전환이 일어나는 수)" 를 사용하여 풀 수 있다고 생각했다.

 

단순 좌표 (y, x) 뿐만 아니라, 사용된 거울 수 및 이동해온 방향 정보가 필요하므로 새로운 구조체를 정의한다.

struct cell{
    int y, x, num, p_dir;
    cell(int y,int x,int num, int p_dir):y(y), x(x), num(num), p_dir(p_dir) {};
};

이동해온 방향(p_dir)을 저장하는 이유는 거울이 사용되는 지점이 방향이 전환되는 시점이기 때문에, 현재 좌표가 어느 방향에서 왔는지 확인하기 위해 필요하다.

 

이 구조체를 이용해 사용된 거울 수(num) 이 가장 작은 순으로 queue 에서 가져오기 위해 우선순위 큐를 사용한다.

 

 

 

 

 우선순위 큐의 Comparator 정의

내가 정의한 구조체에서 max-heap 으로 사용할지  min-heap 으로 사용하지 결정하기 위해 compartor를 정의해야 한다.

방법은 구사과 님의 블로그에 자세히 설명돼있다.

 

풀이에 사용된 방법은 구조체를 이용해 operator() 를 정의해 사용했다.

struct cmp{
    bool operator()(const struct cell& a, const struct cell& b){
        return a.num > b.num;
    }
};

// 중략

priority_queue< cell, vector<cell>, cmp > pq;

 

* 참고로 greater 는 작은 값을 먼저, less 는 큰 값을 먼저 리턴한다.

* a.num > b.num 는 greater 와 같고, a.num < b.num 은 less 와 같다.

 

이렇게 정의된 우선순위 큐를 이용하면, 시작지점에서 거울을 사용하지 않고 최대한 이동하여 탐색한 후,

거울  1개, 2개, k개 사용해서 이동할 수 있는 위치를 순차적으로 탐색할 수 있다.

 

 

 

 

 소스코드

  1. #include<stdio.h>
  2. #include<vector>
  3. #include<queue>
  4.  
  5. using namespace std;
  6.  
  7. struct cell{
  8. int y, x, num, p_dir;
  9. cell(int y,int x,int num, int p_dir):y(y), x(x), num(num), p_dir(p_dir) {};
  10. };
  11. struct cmp{
  12. bool operator()(const struct cell& a, const struct cell& b){
  13. return a.num > b.num;
  14. }
  15. };
  16.  
  17. /*
  18. bool operator<(const struct cell a, const strcut cell b){
  19.   return a.num > b.num;
  20. }
  21. */
  22. int w,h, sy=-1,sx=-1, dy,dx;
  23. int dix[4] = {-1,1,0,0}, diy[4] = {0,0, -1, 1};
  24. char board[111][111];
  25. bool visited[111][111];
  26. bool dir_check(int a, int b){
  27. return (a<2 && b<2) || (a>=2 && b>=2) || a == -1;
  28. }
  29. int main(){
  30. scanf("%d%d",&w,&h);
  31.  
  32. for(int i=0;i<h;i++){
  33. scanf("%s", board[i]);
  34. for(int j=0;j<w;j++){
  35. if(board[i][j] == 'C'){
  36. if(sy != -1 && sx != -1){
  37. dy = i, dx = j;
  38. } else {
  39. sy = i, sx = j;
  40. }
  41. }
  42. }
  43. }
  44. priority_queue< cell, vector<cell>, cmp > pq;
  45. // priority_queue< cell, vector<cell>, greater<cell> > pq;
  46.  
  47. pq.push(cell(sy, sx, 0, -1));
  48. while(!pq.empty()){
  49. cell cur = pq.top();
  50. pq.pop();
  51. visited[cur.y][cur.x] = 1;
  52. if(cur.y == dy && cur.x == dx){
  53. printf("%d\n", cur.num);
  54. break;
  55. }
  56. for(int i=0;i<4;i++){
  57. int ny = cur.y + diy[i], nx = cur.x + dix[i];
  58. if(ny >=0 && nx >=0 && nx < w && ny < h) {
  59. if(!visited[ny][nx] && board[ny][nx] != '*'){
  60. // printf("\tnext : (%d, %d) num : %d, is_plus? : %d\n", ny,nx, cur.num, !dir_check(cur.p_dir, i));
  61. pq.push(cell(ny, nx, cur.num + (dir_check(cur.p_dir, i) ? 0 : 1), i));
  62. }
  63. }
  64. }
  65. }
  66. return 0;
  67. }

 

 

 

'알고리즘 문제풀이' 카테고리의 다른 글

BOJ 2580 스도쿠  (0) 2020.08.20
BOJ 1194 달이 차오른다, 가자.  (0) 2020.08.11
BOJ 11505 구간 곱 구하기  (0) 2020.08.06
1344 축구  (0) 2018.06.01
1351 무한 수열  (0) 2018.05.28

+ Recent posts