프로그래머스 - 안전지대 - C++
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값을 리턴해주면 된다.