https://www.acmicpc.net/problem/30702
문제 요약
국기는 n행 m열의 격자판 ( 행열 )으로 구성되어 있습니다. 격자판의 각 칸을 이루는 색은 A부터 Z까지의 영어 알파벳 대문자로 표현합니다.
A[ i ][ j ] 를 국기 A의 i행 j열의 색이라고 합니다. 두 국기 A, B가 주어졌을 때, 모든 i, j에대해 A[ i ][ j ]와 B[ i ][ j ]가 같으면 둘은 같은 국기 입니다.
국기 A를 적절히 색칠하여 국기 B와 같게 만들려고 합니다. 국기를 색칠할 때는 다음과 같은 동작을 0회 이상 반복해야 합니다.
국기의 격자판 중 한 칸을 고르고, 이 칸과 같은 구역에 속한 모든 칸을 찾는다. 두 칸이 같은색이면서 상하좌우로 인접해 있을 경우 둘은 같은 구역에 속합니다.
이후, 해당 하는 국역의 칸들의 색을 원하는 다른 색으로 바꿉니다.
이 때, 영어 알파벳 대문자 외에도 임의의 다른 색을 새로 사용 할 수 있다.
국기 두 장의 정보가 주어졌을때, 국기 A를 적절히 색칠하여 국기 B와 똑같이 만들 수 있는지 판별해야합니다.
국기는 뒤집거나 돌릴 수 없습니다.
문제 풀이
1. 국기를 2차원 벡터 2개로 입력받습니다.
2. dfs 함수에서는 국기 A를 B로 바꿔주는 기능을 합니다.
국기 A의 0,0부터 탐색하는데 dfs기 때문에 같은 영역일때만 탐색합니다. 여기서 영역은 같은 색깔을 의미하고,
같은 색깔일 경우 국기 B의 0,0 (국기 A의 탐색 시작 노드)의 색과 같은 색으로 덮어 씌웁니다.
국기 A 국기 B
AABBCC DDEEFF
AABBCC DDEEFF
AABBCC DDEEFF
에서 처음 A인 영역을 국기 B의 같은 좌표( 영역 시작 좌표 A의 경우엔 0, 0 )인 색으로 덮어 씌웁니다.
국기 A 국기 B
DDBBCC DDEEFF
DDBBCC DDEEFF
DDBBCC DDEEFF
색깔 A와 같은 영역은 다 변경 되었고 그 다음 방문하지 않은 영역들도 국기 B의 같은 좌표의 색깔로 덮어 씌웁니다.
국기 A 국기 B
DDEEFF DDEEFF
DDEEFF DDEEFF
DDEEFF DDEEFF
만약 같은 색으로 만들 수 없는 국기라면
국기 A 국기 B
AAAA DEEF
BBBB DEEF
CCCC DEEF
국기 A 국기 B
DDDD DEEF
DDDD DEEF
DDDD DEEF
국기 A의 영역 시작 좌표인 국기 B색으로 덮어지기 때문에 D로만 덮어 지게 됩니다.
국기 A의 영역 시작 좌표는 각각 0,0 1,0 2,0 국기 B의 해당 좌표의 색깔은 전부 D이기 때문입니다.
3. dfs를 통해 국기 A의 변경이 끝나면 n*m 2중 배열에서 국기 A와 국기 B의 색깔이 일치하는지 조건을 주고 같을 경우 개수를 셉니다.
4. 세어진 개수가 국기 사이즈와 같을 경우 "YES", 다를 경우 "NO"를 출력합니다.
주의할 점
처음에 풀때는 국기 2개를 입력받고 이를 영역별로 숫자로 바꾸고 다른 영역을 탐색 할 경우 숫자를 증가시켜 바꿔넣게 하였는데
국기 A 국기 B
001122 001122
001122 001122
001122 001122
이렇게 하여 둘이 같은 상태면 "YES"를 출력하게 하였는데 주어진 예제 2개에서는 정답을 뽑을 수 있으나 예외가 있었습니다.
질문 게시판에 있었던 테스트 케이스
2 4
AAAA
BBBB
AAAA
AAAA
를 입력하면
국기 A 국기 B
0000 0000
1111 0000
가 되어
"NO"를 출력하는 예외가 생겼습니다.
따라서 영역의 배치만 같은지 확인하면 틀릴 수 있기 때문에 주의해야합니다.
코드
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int dx[4] = { 0, 1,0 ,-1 };
int dy[4] = { 1,0,-1,0 };
bool visit[51][51];
vector<vector<char>>v1;
vector<vector<char>>v2;
int n, m, cnt= 0;
string s;
void dfs(int x, int y, char c1, char c2)
{
visit[x][y] = true;
v1[x][y] = c2;
for (int i = 0; i < 4; i++)
{
int nx = dx[i] + x;
int ny = dy[i] + y;
if (nx < 0 || nx >= n || ny < 0 || ny >= m)
{
continue;
}
if (!visit[nx][ny])
{
// 같은 영역 색 바꿈
if (v1[nx][ny] == c1)
{
v1[nx][ny] = c2;
dfs(nx, ny, c1, c2);
}
}
}
}
int main()
{
cin >> n >> m;
v1.resize(n, vector<char>(m));
v2.resize(n, vector<char>(m));
// 국기 a 입력
for (int i = 0; i < n; i++)
{
cin >> s;
for (int j = 0; j < m; j++)
{
v1[i][j] = s[j];
}
}
// 국기 b 입력
for (int i = 0; i < n; i++)
{
cin >> s;
for (int j = 0; j < m; j++)
{
v2[i][j] = s[j];
}
}
// 국기 a 기준으로 색 변경
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (!visit[i][j])
{
dfs(i, j, v1[i][j], v2[i][j]);
}
}
}
// 같은지 비교
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (v1[i][j] == v2[i][j])
{
cnt++;
}
}
}
if (cnt == n * m)
{
cout << "YES";
}
else
{
cout << "NO";
}
return 0;
}
예제 1
3 6
AABBCC
AABBCC
AABBCC
DDEEFF
DDEEFF
DDEEFF
결과 1
예제 2
3 4
AAAA
BBBB
CCCC
DEEF
DEEF
DEEF
결과 2
예제3
2 4
AAAA
BBBB
AAAA
AAAA
결과3
'BAEKJOON > DFS' 카테고리의 다른 글
C++ / 1926 / 그림 ( 깊이 우선 탐색 ) (0) | 2024.11.27 |
---|---|
C++ / 4963 / 섬의 개수 ( 깊이 우선 탐색 ) (2) | 2024.11.26 |
C++ / 1081 / 바닥 장식 ( 깊이 우선 탐색 ) (2) | 2024.11.23 |
C++ / 2583 / 영역 구하기 ( 깊이 우선 탐색 ) (0) | 2024.11.18 |
C++ / 11724 / 연결 요소의 개수 ( 깊이 우선 탐색 ) (0) | 2024.11.12 |