[BOJ] 10026번 : 적록색약
1. problem :
https://www.acmicpc.net/problem/10026
2. solution 1 :
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
string board[102];
int vis[102][102];
int row,col; // row == col;
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
int normal_count;
int color_count;
queue<pair<int, int>> Q;
void bfs(int x, int y,char color) {
Q.push({ x,y });
vis[x][y] = 1;
while (!Q.empty()) {
pair<int, int> cur = Q.front(); Q.pop();
for (int dir = 0; dir < 4; dir++) {
int nx = cur.X + dx[dir];
int ny = cur.Y + dy[dir];
if (nx < 0 || nx >= row || ny < 0 || ny >= col) continue;
if (board[nx][ny] != color || vis[nx][ny] != 0) continue;
vis[nx][ny] = 1;
Q.push({ nx,ny });
}
}
}
void color_bfs(int x, int y, char color) {
Q.push({ x,y });
vis[x][y] = 1;
while (!Q.empty()) {
pair<int, int> cur = Q.front(); Q.pop();
for (int dir = 0; dir < 4; dir++) {
int nx = cur.X + dx[dir];
int ny = cur.Y + dy[dir];
if (nx < 0 || nx >= row || ny < 0 || ny >= col) continue;
if (board[nx][ny] == color || vis[nx][ny] != 0) continue;
vis[nx][ny] = 1;
Q.push({ nx,ny });
}
}
}
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> row;
col = row;
for (int i = 0; i < row; i++) cin >> board[i]; // board 채우기 ;
// 정상인부터 시작 Red --> Green --> Blue
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] != 'R' || vis[i][j]) continue;
normal_count++;
bfs(i, j, 'R');
}
}
// 정상인 Green 검사;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] != 'G' || vis[i][j]) continue;
normal_count++;
bfs(i, j, 'G');
}
}
// 정상인 Blue 검사;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] != 'B' || vis[i][j]) continue;
normal_count++;
bfs(i, j, 'B');
}
}
// vis 초기화;
for (int i = 0; i < row; i++) fill(vis[i], vis[i] + col, 0);
// 색맹 검사 ; Blue --> Red_Green; Blue
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] != 'B' || vis[i][j]) continue;
color_count++;
bfs(i, j, 'B');
}
}
// 색맹 검사 ; Red_Green;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] == 'B' || vis[i][j]) continue;
color_count++;
color_bfs(i, j, 'B');
}
}
cout << normal_count << ' ' << color_count << '\n';
return 0;
}
뭔가 코드를 줄일 수 있을 것 같다.
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
string board[102];
int vis[102][102];
int row,col; // row == col;
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
int normal_count;
int color_count;
char colors[3] = { 'R','G','B' };
queue<pair<int, int>> Q;
void bfs(int x, int y,char color) {
Q.push({ x,y });
vis[x][y] = 1;
while (!Q.empty()) {
pair<int, int> cur = Q.front(); Q.pop();
for (int dir = 0; dir < 4; dir++) {
int nx = cur.X + dx[dir];
int ny = cur.Y + dy[dir];
if (nx < 0 || nx >= row || ny < 0 || ny >= col) continue;
if (board[nx][ny] != color || vis[nx][ny] != 0) continue;
vis[nx][ny] = 1;
Q.push({ nx,ny });
}
}
}
void color_bfs(int x, int y, char color) {
Q.push({ x,y });
vis[x][y] = 1;
while (!Q.empty()) {
pair<int, int> cur = Q.front(); Q.pop();
for (int dir = 0; dir < 4; dir++) {
int nx = cur.X + dx[dir];
int ny = cur.Y + dy[dir];
if (nx < 0 || nx >= row || ny < 0 || ny >= col) continue;
if (board[nx][ny] == color || vis[nx][ny] != 0) continue;
vis[nx][ny] = 1;
Q.push({ nx,ny });
}
}
}
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> row;
col = row;
for (int i = 0; i < row; i++) cin >> board[i]; // board 채우기 ;
for (auto c : colors) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] != c || vis[i][j]) continue;
normal_count++;
bfs(i, j, c);
}
}
}
// vis 초기화;
for (int i = 0; i < row; i++) fill(vis[i], vis[i] + col, 0);
// 색맹 검사 ; Blue --> Red_Green; Blue
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] != 'B' || vis[i][j]) continue;
color_count++;
bfs(i, j, 'B');
}
}
// 색맹 검사 ; Red_Green;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] == 'B' || vis[i][j]) continue;
color_count++;
color_bfs(i, j, 'B');
}
}
cout << normal_count << ' ' << color_count << '\n';
return 0;
}
color라는 배열을 만들어서, 정상인의 for문을 1개로 축약했다.
3. solution 2 :
// Authored by : seeys
// Co-authored by : BaaaaaaaaaaarkingDog
// http://boj.kr/99a676d859f54fa0944f81f94ade04a3
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
char board[101][101];
bool vis[101][101];
int n;
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
void bfs(int i, int j) {
queue<pair<int, int>> Q;
Q.push({ i,j });
vis[i][j] = 1;
while (!Q.empty()) {
auto cur = Q.front(); Q.pop();
for (int dir = 0; dir < 4; dir++) {
int nx = cur.X + dx[dir];
int ny = cur.Y + dy[dir];
if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
if (vis[nx][ny] == 1 || board[i][j] != board[nx][ny]) continue;
vis[nx][ny] = 1;
Q.push({ nx,ny });
}
}
}
int area(){
int cnt = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (!vis[i][j]) {
cnt++;
bfs(i, j);
}
}
}
return cnt;
}
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> board[i][j];
}
}
int not_g = area(); //적록색약이 아닌사람
// 적록색약인 사람을 구하기위한 방문배열 초기화
for(int i = 0; i < n; i++)
fill(vis[i], vis[i]+n, false);
// 적록색약은 초록과 빨강을 구분 못하므로 초록이면 빨강으로 바꿔줌
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == 'G')
board[i][j] = 'R';
}
}
int is_g = area(); //적록색약인 사람
cout << not_g << " " << is_g;
return 0;
}
< source code 출처 : https://github.com/encrypted-def/basic-algo-lecture/blob/master/0x09/solutions/10026.cpp >
basic-algo-lecture/0x09/solutions/10026.cpp at master · encrypted-def/basic-algo-lecture
바킹독의 실전 알고리즘 강의 자료. Contribute to encrypted-def/basic-algo-lecture development by creating an account on GitHub.
github.com
이 코드는 정말 느끼는 게 많은 코드다. 내가 color_bfs를 따로 함수를 만든 이유는 R과 G를 또다시 로직을 짜기 위해서인데, G값을 R로 바꿔주면, 기존의 로직으로 작동하게 된다. 또, area라는 함수는 이중 loop를 돌면서 , 아직 방문하지 않은 원소면 bfs를 실행해 버린다. 나는 이 생각을 못해서 , red, green, blue일 때 세 가지의 경우의 수를 직접 작성했다. 그리고, bfs에서 color를 매개변수로 받지 않는 방법은 board [i][j]를 color로 쓰는 것이다. 마지막으로, input 이 들어왔을 때, 예를 들면, "RGBRGB"이때 배열을 char board [][] 형식으로 둘 수 있다는 것도 배운다.