백준 16724

dlwogns·2022년 10월 21일
0

백준

목록 보기
10/34

문제

피리 부는 사나이 성우는 오늘도 피리를 분다.

성우가 피리를 불 때면 영과일 회원들은 자기도 모르게 성우가 정해놓은 방향대로 움직이기 시작한다. 성우가 정해놓은 방향은 총 4가지로 U, D, L, R이고 각각 위, 아래, 왼쪽, 오른쪽으로 이동하게 한다.

이를 지켜보던 재훈이는 더 이상 움직이기 힘들어하는 영과일 회원들을 지키기 위해 특정 지점에 ‘SAFE ZONE’ 이라는 최첨단 방음 시설을 만들어 회원들이 성우의 피리 소리를 듣지 못하게 하려고 한다. 하지만 예산이 넉넉하지 않은 재훈이는 성우가 설정해 놓은 방향을 분석해서 최소 개수의 ‘SAFE ZONE’을 만들려 한다.

성우가 설정한 방향 지도가 주어졌을 때 재훈이를 도와서 영과일 회원들이 지도 어느 구역에 있더라도 성우가 피리를 불 때 ‘SAFE ZONE’에 들어갈 수 있게 하는 ‘SAFE ZONE’의 최소 개수를 출력하는 프로그램을 작성하시오.

입력

첫 번째 줄에 지도의 행의 수를 나타내는 N(1 ≤ N ≤ 1,000)과 지도의 열의 수를 나타내는 M(1 ≤ M ≤ 1,000)이 주어진다.

두 번째 줄부터 N개의 줄에 지도의 정보를 나타내는 길이가 M인 문자열이 주어진다.

지도 밖으로 나가는 방향의 입력은 주어지지 않는다.

출력

첫 번째 줄에 ‘SAFE ZONE’의 최소 개수를 출력한다.

풀이

SAFE ZONE이 어디에 놓으면 좋을지 한번 생각해보자.

이 그림은 예제에 있는 그림이다.
그리고 이 그림은
DLLL
DRLU
RRRU
에서의 Safe zone의 위치를 보여주고 있다.
0,0은 D이므로 1,0으로 가게되고, 1,0도 D이므로 2,0으로 가고, 끝까지 움직이다 보면 결국 다시 0,0으로 돌아오게 된다.
1,1도 R이므로 1,2로 움직이고, 1,2는 L이므로 다시 1,1로 돌아오게 된다.
결국 이 문제는 서로 연결되어 있는 노드들의 집합의 개수를 세면 되는 문제이다.
분리집합으로도 풀 수 있지만, 단순히 DFS하는 과정에 방문한 노드를 표시할때 집합의 번호에 따라 다르게 표시하면 되기 때문에 union-find를 사용하지는 않았다.

정답 코드

#include <iostream>
#include <string>
using namespace std;
int N, M, vis[1001][1001], ans, k=1;
string board[1001];
void func(int x, int y){
    if(x >= N || x<0 || y>=M||y<0)
        return;
    if(vis[x][y] == k)
        return;
    else if(vis[x][y] && vis[x][y] != k){
        ans -= 1;
        return;
    }
    vis[x][y] = k;
    if(board[x][y] == 'U')
        func(x-1,y);
    else if(board[x][y]=='D')
        func(x+1,y);
    else if(board[x][y]=='L')
        func(x,y-1);
    else
        func(x, y+1);
}
int main(){
    cin>>N>>M;
    for(int i=0; i<N; i++)
        cin>>board[i];
    for(int i=0; i<N; i++)
        for(int j=0; j<M; j++){
            if(vis[i][j]) continue;
            func(i,j);
            k++;
            ans += 1;
        }
    cout<<ans;

}
profile
난 커서 개발자가 될래요

0개의 댓글