algorithm

λ°±μ€€ 2151

rkawk 2024. 6. 18. 22:24

문제

더보기

μ±„μ˜μ΄λŠ” κ±°μšΈμ„ λ“€μ—¬λ‹€λ³΄λŠ” 것을 μ°Έ μ’‹μ•„ν•œλ‹€. κ·Έλž˜μ„œ μ§‘ 곳곳에 κ±°μšΈμ„ μ„€μΉ˜ν•΄λ‘κ³  μ§‘ μ•ˆμ„ λŒμ•„λ‹€λ‹ λ•Œλ§ˆλ‹€ κ±°μšΈμ„ 보곀 ν•œλ‹€.

μ±„μ˜μ΄λŠ” μƒˆ ν•΄λ₯Ό λ§žμ΄ν•˜μ—¬ 이사λ₯Ό ν•˜κ²Œ λ˜μ—ˆλŠ”λ°, κ±°μšΈμ„ μ’‹μ•„ν•˜λŠ” κ·Έλ…€μ˜ 성격 λ•Œλ¬Έμ— μƒˆ 집에도 κ±°μšΈμ„ λ§€λ‹¬λ§Œν•œ μœ„μΉ˜κ°€ μ—¬λŸ¬ κ³³ μžˆλ‹€. λ˜ν•œ μ±„μ˜μ΄λ„€ μƒˆ μ§‘μ—λŠ” 문이 두 개 μžˆλŠ”λ°, μ±„μ˜μ΄λŠ” κ±°μšΈμ„ 잘 μ„€μΉ˜ν•˜μ—¬ μž₯λ‚œμ„ 치고 μ‹Άμ–΄μ‘Œλ‹€. 즉, ν•œ μͺ½ λ¬Έμ—μ„œ λ‹€λ₯Έ μͺ½ 문을 λ³Ό 수 μžˆλ„λ‘ κ±°μšΈμ„ μ„€μΉ˜ν•˜κ³  μ‹Άμ–΄μ‘Œλ‹€.

μ±„μ˜μ΄λ„€ 집에 λŒ€ν•œ 정보가 μ£Όμ–΄μ‘Œμ„ λ•Œ, ν•œ μͺ½ λ¬Έμ—μ„œ λ‹€λ₯Έ μͺ½ 문을 λ³Ό 수 μžˆλ„λ‘ ν•˜κΈ° μœ„ν•΄ μ„€μΉ˜ν•΄μ•Ό ν•˜λŠ” 거울의 μ΅œμ†Œ 개수λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

κ±°μšΈμ„ μ„€μΉ˜ν•  λ•Œμ—λŠ” 45도 κΈ°μšΈμ–΄μ§„ λŒ€κ°μ„  λ°©ν–₯으둜 μ„€μΉ˜ν•΄μ•Ό ν•œλ‹€. λ˜ν•œ λͺ¨λ“  κ±°μšΈμ€ μ–‘λ©΄ 거울이기 λ•Œλ¬Έμ— μ–‘ μͺ½ λͺ¨λ‘μ—μ„œ λ°˜μ‚¬κ°€ 일어날 수 μžˆλ‹€. μ±„μ˜μ΄λŠ” κ±°μšΈμ„ 맀우 많이 κ°€μ§€κ³  μžˆμ–΄μ„œ 거울이 λΆ€μ‘±ν•œ κ²½μš°λŠ” μ—†λ‹€κ³  ν•˜μž.

κ±°μšΈμ„ μ–΄λ–»κ²Œ μ„€μΉ˜ν•΄λ„ ν•œ μͺ½ λ¬Έμ—μ„œ λ‹€λ₯Έ μͺ½ 문을 λ³Ό 수 μ—†λŠ” κ²½μš°λŠ” μ£Όμ–΄μ§€μ§€ μ•ŠλŠ”λ‹€.

 

 

첫째 쀄에 μ§‘μ˜ 크기 N (2 ≤ N ≤ 50)이 μ£Όμ–΄μ§„λ‹€. λ‹€μŒ N개의 μ€„μ—λŠ” N개의 문자둜 집에 λŒ€ν•œ 정보가 μ£Όμ–΄μ§„λ‹€. ‘#’λŠ” 문이 μ„€μΉ˜λœ 곳으둜 항상 두 곳이며, ‘.’은 아무 것도 μ—†λŠ” κ²ƒμœΌλ‘œ 빛은 이 곳을 ν†΅κ³Όν•œλ‹€. ‘!’은 κ±°μšΈμ„ μ„€μΉ˜ν•  수 μžˆλŠ” μœ„μΉ˜λ₯Ό λ‚˜νƒ€λ‚΄κ³ , ‘*’은 빛이 톡과할 수 μ—†λŠ” 벽을 λ‚˜νƒ€λ‚Έλ‹€.

풀이

λ‹€μ΅μŠ€νŠΈλΌλ‘œ ν’€μ—ˆλ‹€.

λ‹€μŒκ³Ό 같은 μ˜ˆμ œκ°€ μžˆμ„λ•Œ 첫번째 λ¬ΈλΆ€ν„° μ‹œμž‘ν•˜λ©΄

λ‹€μŒκ³Ό 같은 λ°©ν–₯으둜 갈 수 있고, κ±°μšΈμ„ μ§€λ‚˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— μ‚¬μš©ν•œ 거울의 개수λ₯Ό 0으둜 μ²΄ν¬ν•œλ‹€.

λ‹€μŒ μ§„ν–‰λ°©ν–₯은 ν˜„μž¬ 지점이 거울이 μ•„λ‹ˆμ—ˆκΈ° λ•Œλ¬Έμ— λ°©ν–₯을 λ°”κΏ€ 수 μ—†κ³ , κ·ΈλŒ€λ‘œ μ§„ν–‰ν•΄μ„œ ν•΄λ‹Ή 거울둜 κ°€κ²Œλœλ‹€.

κ·Έ λ‹€μŒ μ§„ν–‰λ°©ν–₯은 μ΄λ ‡κ²Œ 되며,  ν˜„μž¬ 지점이 거울이기 λ•Œλ¬Έμ— μ‚¬μš©ν•œ 거울 + 1을 ν•˜μ—¬ λ‹€μŒ μ§€μ μœΌλ‘œ μ΄λ™ν•œλ‹€.

 

μ΄λŸ¬ν•œ λ°©μ‹μœΌλ‘œ [지점][λ°©ν–₯]에 λŒ€ν•œ μ΅œμ†Œ 거울의 μ‚¬μš©κ°œμˆ˜λ₯Ό μ²΄ν¬ν•œλ‹€λ©΄ 문제λ₯Ό ν’€ 수 μžˆλ‹€.

 

ν˜„μž¬ μ§€μ μ˜ 경우의 μˆ˜λŠ” 3κ°€μ§€λ‘œ, {#, ., !} 의 경우의 μˆ˜κ°€ μžˆλ‹€.

#인 κ²½μš°μ—λŠ” λ°©ν–₯의 μ œν•œμ΄ μ—†κ³ 

.인 κ²½μš°μ—λŠ” 이전에 μ§„ν–‰ν–ˆλ˜ λ°©ν–₯λŒ€λ‘œ μ§„ν–‰ν•΄μ•Όν•˜λ©°

!인 κ²½μš°μ—λŠ” 이전에 μ§„ν–‰ν–ˆλ˜ λ°©ν–₯의 λ°˜λŒ€λ°©ν–₯을 μ œμ™Έν•˜κ³  이동할 수 μžˆλ‹€κ³  κ°€μ •ν–ˆλ‹€.

 

μ½”λ“œ

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
using namespace std;
int N, dx[4]={0,1,0,-1}, dy[4]={1,0,-1,0}, ans[51][51][4], ansNum = 987654322, startX, startY;
string board[51];
void solve(int x, int y) {
    queue<pair< pair<int, int>, pair<int, int> > >q;
    q.push(make_pair(make_pair(x, y), make_pair(-1, 0)));
    while(!q.empty()) {
        auto cur = q.front().first; int curDir = q.front().second.first; int curDist = q.front().second.second; q.pop();
        char curBoard = board[cur.first][cur.second];
        if(curBoard == '#') {
            for(int dir=0; dir<4; dir++) {
                int nx = cur.first + dx[dir];
                int ny = cur.second + dy[dir];
                if(nx<0||nx>=N||ny<0||ny>=N||board[nx][ny] == '*') continue;
                if(ans[nx][ny][dir] > curDist) {
                    ans[nx][ny][dir] = curDist;
                    q.push(make_pair(make_pair(nx,ny), make_pair(dir, curDist)));
                }
                if(board[nx][ny] == '#'&& (nx != startX || ny != startY)) ansNum = min(ansNum, ans[nx][ny][dir]);
            }
        }else if(curBoard == '!') {
            for(int dir=0; dir<4; dir++) {
                if(dir == (curDir+2)%4) continue;
                int nx = cur.first + dx[dir];
                int ny = cur.second + dy[dir];
                if(nx<0||nx>=N||ny<0||ny>=N||board[nx][ny] == '*') continue;
                int addiDist = (curDir == dir)?0:1;
                if(ans[nx][ny][dir] > curDist + addiDist) {
                    ans[nx][ny][dir] = curDist + addiDist;
                    q.push(make_pair(make_pair(nx,ny), make_pair(dir, curDist + addiDist)));
                }
                if(board[nx][ny] == '#' && (nx != startX || ny != startY)) ansNum = min(ansNum, ans[nx][ny][dir]);
            }
        }else if(curBoard == '.') {
            int nx = cur.first + dx[curDir];
            int ny = cur.second + dy[curDir];
            if(nx<0||nx>=N||ny<0||ny>=N||board[nx][ny] == '*') continue;
            if(ans[nx][ny][curDir] > curDist) {
                ans[nx][ny][curDir] = curDist;
                q.push(make_pair(make_pair(nx,ny), make_pair(curDir, curDist)));
            }
            if(board[nx][ny] == '#'&& (nx != startX || ny != startY)) ansNum = min(ansNum, ans[nx][ny][curDir]);
        }
    }
}
int main(){
    cin>>N;
    for(int i=0; i<N; i++) cin>>board[i];
    for(int i=0; i<N; i++)
        for(int j=0; j<N; j++){
            if(board[i][j] == '#'){
                startX = i; startY = j;
            }
            for(int k=0; k<4; k++)
                ans[i][j][k] = 987654321;
        }
    for(int i=0; i<4; i++)
        ans[startX][startY][i] = 0;
    solve(startX, startY);
    cout<<ansNum;
    

}