알고리즘/프로그래머스 1단계

프로그래머스 - 안전지대 - C++

게임만드는학생 2023. 9. 11. 17:41

https://school.programmers.co.kr/learn/courses/30/lessons/120866

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

#include <string>
#include <vector>

using namespace std;

int posX[8]={1,1,1,0,-1,-1,-1,0};
int posY[8]={-1,0,1,1,1,0,-1,-1};

int solution(vector<vector<int>> board) {
    int n =board.size();
    int answer = n*n;
    
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(board[i][j]==1)
            {
                answer--;
                for(int k=0;k<8;k++)
                {
                    if(i+posY[k]>=0&&i+posY[k]<n&&j+posX[k]>=0&&j+posX[k]<n)
                    {
                        if(board[i+posY[k]][j+posX[k]]==0)
                        {
                            board[i+posY[k]][j+posX[k]]=2;answer--;
                        }   
                    }
                }
            }
        }
    }
    
    return answer;
}

 

설명

이 문제는 board 배열에서 지뢰의 피해없이 안전한 곳이 어딘지를 체크해서 그 칸의 수를 반환하는 문제이다. 

이 때, 안전한 곳이란 지뢰가 설치된 칸 + 지뢰가 있는 인접 8칸을 제외한 곳이 안전한 곳이다. 

 

1. 따라서 for문을 돌면서 지뢰가 설치돼있는 곳을 찾고 

2. 그 인접지역을 표시한다. 

3. 안전지역의 개수를 업데이트한다.

 

이를 위해 먼저 모든 곳이 안전한 곳이라는 가정하에 answer의 값을 n*n으로 설정한다.

그리고 지뢰설치지역과 인접지역에서 1씩 깎는다. 

 

i,j를 이용한 2중 for문을 돌면서 각 board 위치에 접근한다. 

 

 if(board[i][j]==1)

즉, 값이 1인곳이 지뢰가 설치돼있는거니까 이 때, 그 인접지역을 표시하면 된다. 

 

answer--;
                for(int k=0;k<8;k++)
                {
                    if(i+posY[k]>=0&&i+posY[k]<n&&j+posX[k]>=0&&j+posX[k]<n)
                    {
                        if(board[i+posY[k]][j+posX[k]]==0)
                        {
                            board[i+posY[k]][j+posX[k]]=2;answer--;
                        }   
                    }
                }

여기서 먼저 지뢰있는 곳을 발견했으니 answer값을 1 감소시킨다. 

 

그리고 for문을 돌며 인접지역을 체크한다. 

int posX[8]={1,1,1,0,-1,-1,-1,0};
int posY[8]={-1,0,1,1,1,0,-1,-1};

for문을 이용해 주변을 확인하기 위해서 8칸으로 접근하기위한 각각의 값을 미리 배열로 저장했다. 

예를들어, 위로 갈거면 (y,x) 기준 (-1,0) 이다. 따라서 y+posY[7], x+posX[7] 하면 위쪽칸을 보게된다. 

 

위 배열을 기준으로 for문을 돌며 if문을 확인한다.

if(i+posY[k]>=0&&i+posY[k]<n&&j+posX[k]>=0&&j+posX[k]<n)
                    {
                        if(board[i+posY[k]][j+posX[k]]==0)
                        {
                            board[i+posY[k]][j+posX[k]]=2;answer--;
                        }   
                    }

복잡해 보이지만 사실 현재위치에서 주변지역을 보려할 때, 보드의 범위를 벗어나는지 체크하는 것이다.

board의 인덱스는 가로,세로 전부 0~n-1 까지이다. 

따라서 그 범위가 벗어나지 않아야한다. 

 

그리고 board값이 0이어야한다. 

 

만약 주변지역의 값이 1이면 지뢰이기 때문에 그 위치를 기점으로 다시 주변지역을 탐색해야한다. 

그리고 값이 2이면 지뢰의 주변지역이라고 정하였다. 

따라서 0일때만 수행하여 칸의 값을 2로바꾸고 answer를 1감소시킨다. 

 

이렇게하면 여러 지뢰에 의해 중복되는 주변지역으로 중복감소되는 것을 막을 수 있다.

 

마지막으로 answer값을 리턴해주면 된다.