[ 백준 ] 2564 / 경비원

金弘均·2021년 9월 15일
0

Baekjoon Online Judge

목록 보기
86/228
post-thumbnail
post-custom-banner

# Appreciation

/*
 * Problem :: 2564 / 경비원
 *
 * Kind :: Simulation
 *
 * Insight
 * - 가로 길이=C
 *   세로 길이=R
 *   전체 직사각형 길이=2*C+2*R
 *   상점의 위치=(위치한 방향=sp, 경계로부터의 거리=sd)
 *   동근이의 위치=(위치한 방향=xp, 경계로부터의 거리=xd)
 *   + 전체 직사각형 길이 = 상점으로부터 동근이까지 시계방향 거리 + 반시계방향 거리
 *     시계방향 거리를 구해볼가?
 *     # 그런데... 1 <= sp,xp <= 4 의 가능한 조합을 모두 다루어야 한다
 *       하드코딩으로 각 경우에 어떻게 계산해야하는지를 알아내면 되지만... 너무 귀찮다
 *       더 간결한 방법 없을까?
 *
 * - 일단 동근이와 상점들의 좌표를 직교좌표계 방식으로 구하자 <= 생각하기 편하게 하기 위해
 *   맨 왼쪽 위의 점을 (0,0) 으로 설정하였다
 *   + 에제 입력 1
 *     10 5
 *     3
 *     1 4 => 직교좌표계로는 (0,4)
 *     3 2 => 직교좌표계로는 (2,0)
 *     2 8 => 직교좌표계로는 (5,8)
 *     2 3 => 직교좌표계로는 (5,3)
 *     # 상점의 위치=(위치한 방향=sp, 행=sr, 열=sc)
 *       동근이의 위치=(위치한 방향=xp, 행=xr, 열=xc)
 *       dy = abs(xr-sr), dx = abs(xc-sc)
 *       상점과 동근이와의 최단거리 = dy+dx
 *       -> 그러나 이 경우는 상점과 동근이가 마주보는 위치에 있으면 성립하지 않는다!
 *          인접한 위치의 방향이거나 같은 위치의 방향이면 위의 식으로 계산이 되지만
 *          마주보는 경우는 따로 처리해주어야 한다
 *          => 간단히 계산하는 식이 있나 끙끙거리며 생각해봤지만... 생각나는게 없었다 ㅠ
 *             그럼 그냥 해야지 뭐 ㅋ
 *
 * Point
 * - pair<int,int> 를 써서 편하게 비교하려 했다
 *   + typedef pair<int,int> pii 로 축약하여 사용했다
 *     # braces 로만은 비교가 안되더라
 *       pii pos = {1, 2}
 *       if (pos == {1, 2}) => Error
 *       if (pos == pii{1, 2}) => Okay
 */

# Code

//
//  BOJ
//  ver.C++
//
//  Created by GGlifer
//
//  Open Source

#include <iostream>

using namespace std;

#define endl '\n'

// Set up : Global Variables
struct Point { int r, c, p; };
typedef pair<int,int> pii;

// Set up : Functions Declaration
/* None */


int main()
{
    // Set up : I/O
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // Set up : Input
    int C, R;
    cin >> C >> R;
    int N; cin >> N;
    Point S[N+1];
    for (int i=0; i<N+1; i++) { /* 동근이의 위치까지 한번에 받음 */
        int p, d;
        cin >> p >> d;
        int r, c;
        switch (p) { /* 주어진 위치를 바탕으로 직교좌표계로 변환 */
            case 1: r = 0; c = d; break;
            case 2: r = R; c = d; break;
            case 3: r = d; c = 0; break;
            case 4: r = d; c = C; break;
            default: throw invalid_argument("Invalid Position");
        } S[i] = {r, c, p};
    }

    // Process
    /* 동근이의 위치
     * xr = 직교좌표계에서 동근이가 위치한 행
     * xc = 직교좌표계에서 동근이가 위치한 열
     * xp = 직교좌표계에서 동근이가 위치한 방향 (북,남,동,서) */
    int xr = S[N].r, xc = S[N].c, xp = S[N].p;
    int ans = 0;
    for (int i=0; i<N; i++) {
        /* 상점의 위치
         * sr = 직교좌표계에서 상점이 위치한 행
         * sc = 직교좌표계에서 상점이 위치한 열
         * sp = 직교좌표계에서 상점이 위치한 방향 (북,남,동,서) */
        int sr = S[i].r, sc = S[i].c, sp = S[i].p;
        /* 동근이와 상점이 위치한 방향들
         * min, max 를 사용해서 정렬 */
        pii pos = {min(xp,sp), max(xp,sp)};
        int dy = abs(xr-sr), dx = abs(xc-sc); /* 마주보지 않는 경우
                                               * 동근이와 상점의 최단 거리 */
        if (pos == pii{1,2}) { /* 동근이와 상점이 북,남으로 마주보고 있으면 */
            dx = min(xc+sc, 2*C-(xc+sc)); /* dx 수정 */
        }
        if (pos == pii{3,4}) { /* 동근이와 상점이 동,서로 마주보고 있으면 */
            dy = min(xr+sr, 2*R-(xr+sr)); /* dy 수정 */
        } ans += dx+dy;
    }

    // Control : Output
    cout << ans << endl;
}

// Helper Functions
/* None */
profile
이런 미친 게임을 봤나! - 옥냥이
post-custom-banner

0개의 댓글