반응형

문제링크:https://www.acmicpc.net/problem/9663

 

9663번: N-Queen

N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다. N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.

www.acmicpc.net

 

dfs문제이고 백트래킹에서 대표적인 문제입니다.

15X15체스판까지 가능합니다. 

하지만 dfs 구현시 함수에서 NxN번 반복하면 당연히 시간초과입니다.  

다른방법을 생각해야합니다.

 

퀸은 자기의 양옆과 대각선 모두 이동이 가능합니다. 즉 행단위로 검사해도 괜찮습니다. 어차피 퀸이 있는 행에는 퀸이 있을 수 없기떄문입니다. 그렇기 때문에 열값은 count값을 사용합니다. ( 퀸이 체스판에 있을때마다 1씩증가)

 

n=4라면 답은 2입니다.

 

0 0 1 0
1 0 0 0
0 0 0 1
0 1 0 0

0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0

 

 

 

 

우선 정답코드입니다.

#include <iostream>
using namespace std;

int n = 0, result  = 0;
bool visited[15][15] = { 0 };

bool available(int i, int cnt) {

	int x, y;
	for (x = 0; x < cnt; x++) {
		if (visited[i][x]) return false;
	}

	for (x = cnt - 1, y = i - 1; y >= 0; x--, y--) {
		if (visited[y][x]) return false;
	}

	for (x = cnt - 1, y = i + 1; y < n; x--, y++) {
		if (visited[y][x]) return false;
	}

	return true;
}

void dfs(int cnt) {

	if (cnt == n) {
	
		result++;
		return;
	}
	for (int i = 0; i < n; i++) {
		if (!visited[i][cnt] && available(i, cnt)) {

			visited[i][cnt] = 1;
			dfs(cnt + 1);
			visited[i][cnt] = 0;
		}
	}

	

}
int main(){

	cin >> n;

	dfs(0);
		
	cout << result << endl;

	return 0;
}


 

 

아래가 재귀루트입니다.

for (int i = 0; i < n; i++) {
		if (!visited[i][cnt] && available(i, cnt)) {

			visited[i][cnt] = 1;
			dfs(cnt + 1);
			visited[i][cnt] = 0;
		}
	}

 

행은 0~n-1 까지 이동하며 검사하고 열값은 체스판에 퀸을 올려놓을때 마다 1씩증가하며 위치를 찾습니다. 

 

 

아래는 검사함수입니다.

bool available(int i, int cnt) {

	int x, y;
	for (x = 0; x < cnt; x++) {
		if (visited[i][x]) return false;
	}

	for (x = cnt - 1, y = i - 1; y >= 0; x--, y--) {
		if (visited[y][x]) return false;
	}

	for (x = cnt - 1, y = i + 1; y < n; x--, y++) {
		if (visited[y][x]) return false;
	}

	return true;
}

 

 

자신의 왼쪽에 퀸이 있는지 확인하는 과정입니다. 

반응형

'알고리즘 > DFS' 카테고리의 다른 글

[백준] 14267-내리 칭찬(C++)  (0) 2021.01.01
[백준] 2580-스도쿠(C++)  (0) 2020.08.19
[백준] 2573-빙산(C++)  (0) 2020.06.09
[백준] 1987-알파벳(C++)  (0) 2020.06.09
[백준] 1062-가르침(C++)  (0) 2020.05.05
반응형

문제링크:https://www.acmicpc.net/problem/2573

 

2573번: 빙산

첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을 �

www.acmicpc.net

 

dfs 유형으로 분류되지만... 사실 단순 구현문제였습니다.

 

 

빙산이 몇개인지 확인하고, 빙산을 녹이고, 하는 과정을 구현하여 결과를 도출하면 됩니다.

 

알고리즘입니다.

  • 1. 빙산이 몇조각인지 확인하기
  • 2. 두조각 이상인지 확인하기
  • 3. 얼음 녹이기 
  • 4. 얼음이 다녹은지 확인

빙하가 몇조각인지 확인할 때에는 dfs 나 bfs중 편한것을 사용하시면 됩니다. 

 

#include <iostream>
#include <cstring>
using namespace std;
int n = 0, m = 0, result = 0;
int arr[300][300] = { 0 };
int temp[300][300] = { 0 };
int x_ar[4] = { 0,0,-1,1 };
int y_ar[4] = { 1,-1,0,0 };


void dfs(int yy,int xx,int cnt) {
	temp[yy][xx] = cnt; //temp에 표시 

	for (int i = 0; i < 4; i++) {
		int y = yy + y_ar[i];
		int x = xx + x_ar[i];
		if (y >= 0 && y < n&&x >= 0 && x < m)
			if (arr[y][x] && temp[y][x] == 0) 
				dfs(y, x, cnt);
			
	}
}
void melt_ice() {
	int melt = 0;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++) {
			if (arr[i][j] == 0) continue;
			melt = 0;
			for (int k = 0; k < 4; k++) {
				int y = i + y_ar[k];
				int x = j + x_ar[k];
				if (arr[y][x] == 0 && y >= 0 && y < n && x >= 0 && x < m)
					melt++;
			}

			if (arr[i][j] < melt) continue;
			else temp[i][j] = arr[i][j] - melt;
		}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			arr[i][j] = temp[i][j];
}


int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			cin >> arr[i][j];

	while (1) {
		//1. 빙산이 몇조각인지 확인하기
		memset(temp, 0, sizeof(temp));
		int cnt = 0;
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++)
				if (arr[i][j] && temp[i][j] == 0) {
					cnt++;
					dfs(i, j, cnt);
				}
		//2. 두조각 이상인지 확인하기 
		if (cnt >= 2) {
			cout << result << endl;
			return 0;
		}
		//3. 얼음 녹이기 
		memset(temp, 0, sizeof(temp));
		melt_ice();
		//4. 얼음이 다녹은지 확인
		bool jud = false;
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++)
				if (arr[i][j]) jud = true;

		if (jud == false) {
			cout << 0 << endl;
			return 0;
		}

		//카운트 증가
		result++;
	}
}
반응형

'알고리즘 > DFS' 카테고리의 다른 글

[백준] 2580-스도쿠(C++)  (0) 2020.08.19
[백준] 9663-N-Queen(C++)  (0) 2020.07.27
[백준] 1987-알파벳(C++)  (0) 2020.06.09
[백준] 1062-가르침(C++)  (0) 2020.05.05
[백준] 1012-유기농 배추(C++)  (0) 2020.03.31
반응형

문제링크:https://www.acmicpc.net/problem/1987

 

1987번: 알파벳

문제 세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한

www.acmicpc.net

 

전형적인 dfs 문제입니다. 수의 범위도 20까지 이기때문에 무조건 dfs 구현이구나 생각했습니다.

 

생각보다 쉽게 문제를 풀어 의아했습니다. 별다른 가지치기를 하지 않고 ac를 받았기 때문입니다. 

 

#include <iostream>
#include <string>
using namespace std;
int result = 0;
bool al[26] = { 0 };
int x_ar[4] = { 0,0,1,-1 };
int y_ar[4] = { 1,-1,0,0 };
int r = 0, c = 0;
string arr[20];
void dfs(int yy,int xx,int cnt) {
	if (cnt > result) { 
		result = cnt; 
	}

	for (int i = 0; i < 4; i++) {
		int y = y_ar[i] + yy;
		int x = x_ar[i] + xx;
		if (y >= 0 && y < r && x >= 0 && x < c) {
			if (al[arr[y][x] - 65] == 0) {
				al[arr[y][x] - 65] = 1;
				dfs(y, x, cnt + 1);
				al[arr[y][x] - 65] = 0;
			}
		}
	}
	return;

}

int main(){
	cin >> r >> c;
	for (int i = 0; i < r; i++)
		cin >> arr[i];
	
	
	al[arr[0][0] - 65] = 1;
	dfs(0, 0, 1);
	al[arr[0][0] - 65] = 0;
			
	
	cout << result << endl;
}

 

왜 백트래킹에 들어가는지 아직도 잘 모르겠습니다...

대문자 A가 아스킷 코드값으로 65이기 때문에 아래와 같이 마킹을 해주었습니다.

 

화이팅!!

 

 

 

반응형

'알고리즘 > DFS' 카테고리의 다른 글

[백준] 9663-N-Queen(C++)  (0) 2020.07.27
[백준] 2573-빙산(C++)  (0) 2020.06.09
[백준] 1062-가르침(C++)  (0) 2020.05.05
[백준] 1012-유기농 배추(C++)  (0) 2020.03.31
[백준] 2661-좋은수열(C++)  (0) 2020.03.30
반응형

문제링크:https://www.acmicpc.net/problem/1062

 

1062번: 가르침

첫째 줄에 단어의 개수 N과 K가 주어진다. N은 50보다 작거나 같은 자연수이고, K는 26보다 작거나 같은 자연수 또는 0이다. 둘째 줄부터 N개의 줄에 남극 언어의 단어가 주어진다. 단어는 영어 소문자로만 이루어져 있고, 길이가 8보다 크거나 같고, 15보다 작거나 같다. 모든 단어는 중복되지 않는다.

www.acmicpc.net

 

브루트 포스문제이고 dfs를 통해서 구현해야하는 문제였습니다.

 

기본적인 구현은 dfs를 통한 재귀로 구현해주시면 됩니다.

문제는 시간초과문제입니다.

 

확인해야하는 알파벳은 26-5 =21개입니다. 

이때 매번 15-8 =7개 * 50개 의 알파벳을 확인해주는 재귀이기 때문에 가지치기를 잘해야하는 문제였습니다.

 

가지치기

  •  1. k <5, k==26의 극단값 처리 (엄연하게 백트래킹 가지치기는 아니죠)
  •  2. dfs에 alpha 변수를 통해서 알파벳 중에서 k-5개를 선택할 때 중복이 안 생기도록 만들기 (이게 백트래킹의 핵심입니다.)
  •  3. set 컨테이너를 통해서 arr안에 들어가는 알파벳의 중복을 제거했습니다. (안해도 통과는 됩니다.)

정답 코드입니다. 

#include <algorithm>
#include <iostream>
#include <string>
#include <set>
using namespace std;
bool visited[26] = { 0 };
set<char> arr[51];
int n = 0, k = 0, result = 0;

void dfs(int alpha, int cnt) {
	if (cnt == (k - 5)) {
		int cnt = 0;
		for (int i = 0; i < n; i++) {
			bool jud = true;

			for (auto it = arr[i].begin(); it != arr[i].end(); it++) {
				if (visited[*it - 'a'] == 0) {
					jud = false;
					break;
				}
			}
			
			if (jud == true)
				cnt++;
		}
		 result = max(result,cnt);

		return;
	}

	for (int i = alpha; i < 26; i++) {

		if (visited[i] == 0) {
			visited[i] = 1;
			dfs(i,cnt + 1);
			visited[i] = 0; 
		}
	}

}

int main() {

	ios_base::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> k;
	visited['a' - 'a'] = 1;
	visited['c' - 'a'] = 1;
	visited['i' - 'a'] = 1;
	visited['t' - 'a'] = 1;
	visited['n' - 'a'] = 1;

	for (int i = 0; i < n; i++) {
		string v;
		cin >> v;
		for (int j = 0; j < v.size(); j++) {
			if (v[j] != 'a' && v[j] != 'c' && v[j] != 'i' && v[j] != 't' && v[j] != 'n') {
				arr[i].insert(v[j]);
			}
		}
			
	}
	

	if (k < 5) {
		cout << 0 << '\n';
		return 0;
	}
	else if (k == 26) {
		cout << n << '\n';
		return 0;
	}
	dfs(0,0);

	cout << result << '\n';
}
반응형

'알고리즘 > DFS' 카테고리의 다른 글

[백준] 2573-빙산(C++)  (0) 2020.06.09
[백준] 1987-알파벳(C++)  (0) 2020.06.09
[백준] 1012-유기농 배추(C++)  (0) 2020.03.31
[백준] 2661-좋은수열(C++)  (0) 2020.03.30
[백준] 15666-N과 M (12)(C++)  (0) 2020.03.25
반응형

문제 링크:https://www.acmicpc.net/problem/1012

 

1012번: 유기농 배추

차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약을 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 효과적인 배추흰지렁이를 구입하기로 결심한다. 이 지렁이는 배추근처에 서식하며 해충을 잡아 먹음으로써 배추를 보호한다. 특히, 어떤 배추에 배추흰지렁이가 한 마리라도 살고 있으면 이 지렁이는 인접한 다른 배추로 이동할 수 있어, 그 배추들 역시 해충으로부터 보호받을 수 있다. (

www.acmicpc.net

 

dfs, bfs 를 사용하는 완전 탐색 문제였습니다. 

1인 위치의 상하좌우를 이동하며 해당위치가 1인지, 방문 한적 있는지 판단하는 문제였습니다.

bfs 보다는 dfs 로 구현하는게 좋은 문제였습니다.

 

 

저는 큐를 탐색하는 형태인 bfs로 탐색하며 dfs를 추가로 사용해서 구현하였습니다.

#include <iostream>
#include <cstring>
using namespace std;

int t = 0, k = 0, m = 0, n = 0;
int	arr[51][51];
bool visited[51][51];
int que[2500][2];
int started = 0, ended = 0;
int result = 0;

int x_ar[4] = { -1,1,0,0 };
int y_ar[4] = { 0,0,1,-1 };
void dfs(int y, int x);
void bfs() {

	while (started != ended) {
		
		int x = que[started][0];
		int y = que[started++][1];
		if (visited[y][x] == 1) continue;
		
		result++;

		dfs(y, x);

	}
}
void dfs(int y, int x) {
	visited[y][x] = 1;

	for (int i = 0; i < 4; i++) {
		int yy = y + y_ar[i];
		int xx = x + x_ar[i];
		if (yy >= 0 && yy < n && xx >= 0 && xx < m) {
			if(arr[yy][xx] == 1 &&visited[yy][xx] == 0)
				dfs(yy, xx);
		}
	}

}

int main() {

	cin >> t;

	while (t--) {

		cin >> m >> n >> k;
		started = 0, ended = 0;
		result = 0;
		memset(arr, 0, sizeof(arr));
		memset(que, 0, sizeof(que));
		memset(visited, 0, sizeof(visited));
		int x, y;

		for (int i = 0; i < k; i++) {
			cin >> que[ended][0] >> que[ended][1];
			arr[que[ended][1]][que[ended][0]] = 1;
			ended++;

		}
		
		bfs();
		
		cout << result << endl;
	}
}

 

 

 

더욱 최적화 된 코드입니다.

다시 풀어본 문제인데, 1년전에 풀었던 코드가 훨씬 효율이 좋아서 현타가 왔습니다... 

굳이 큐를 사용할 필요 없는 문제였습니다. ( 위의 코드는 사실 큐라고 하기에도 애매한 배열의 사용형태입니다..)

#include <iostream>
#include <string.h>
using namespace std;
 
int dy[4]={1,-1,0,0};
int dx[4]={0,0,1,-1};
int M,N,K;
int arr[50][50]={0};
int visited[50][50]={0};
 
void dfs(int y,int x){
    
    for(int i=0;i<4;i++){
        int ny=y+dy[i];
        int nx=x+dx[i];
        
        if(ny<0 || ny>=N || nx<0 || nx>=M)
            continue;
        
        if(arr[ny][nx] && !visited[ny][nx]){
            visited[ny][nx]++;
            dfs(ny,nx);
        }
    }
}
int main(){
    int T,x,y;
    cin>>T;
    
    for(int testCase=0;testCase<T;testCase++){
        scanf("%d %d %d",&M,&N,&K);
        
        memset(arr,0,sizeof(arr));
        memset(visited,0,sizeof(visited));
        
        int ans=0; //지렁이 개수
        
        for(int i=0;i<K;i++){
            scanf("%d %d",&x,&y);
            arr[y][x]=1;
        }
        
        for(int i=0;i<N;i++)
            for(int j=0;j<M;j++)
                if(arr[i][j] && !visited[i][j]){
                    
                    ans++;
                    visited[i][j]++;
                    dfs(i,j);
                    
                }
        
        cout<<ans<<endl;
    }
    return 0;
}

 

꼭 직접 작성하면서 풀어보세요! 화이팅 :)

 

반응형

'알고리즘 > DFS' 카테고리의 다른 글

[백준] 1987-알파벳(C++)  (0) 2020.06.09
[백준] 1062-가르침(C++)  (0) 2020.05.05
[백준] 2661-좋은수열(C++)  (0) 2020.03.30
[백준] 15666-N과 M (12)(C++)  (0) 2020.03.25
[백준] 10026-적록색약(C++)  (0) 2020.03.12
반응형

문제링크:https://www.acmicpc.net/problem/2661

 

2661번: 좋은수열

첫 번째 줄에 1, 2, 3으로만 이루어져 있는 길이가 N인 좋은 수열들 중에서 가장 작은 수를 나타내는 수열만 출력한다. 수열을 이루는 1, 2, 3들 사이에는 빈칸을 두지 않는다.

www.acmicpc.net

 

정답률에 비해서 어려운 문제였습니다.

우선, 규칙성이 있는지 확인하셔야 합니다. 하지만 수가 늘어남에 따라 규칙성이 변화하는 형태로 별다른 규칙이 없었습니다. 그렇다면 완전탐색을 고려해보아야 합니다. 마침 n도 1 이상 80이하로 비교적 적은 수 입니다. 단순히 모든 수를 넣어보고 비교한다면 시간초과가 날 것입니다. 백트래킹에 대한 개념을 아셔야 합니다.

 

 

백트래킹이란?

주로 dfs에서 사용되는 개념입니다. 가지치기라고 생각하면 됩니다. 완전탐색시에 모든 경우의 수 를 고려해서 결과를 도출합니다. 하지만 완탐은 시간이 어마어마하게 들어가는 비효율적인 방법입니다. 

백트래킹은 완전탐색시에 가능성이 있는 경우의 수들만 추려내면서 탐색을 하는 방법입니다.  

 

이번 문제는 직접 코드를 보시는게 이해가 빠릅니다. 

#include <iostream>
#include <string>
using namespace std;
int n = 0;
bool ended = 0;
bool isValid(string val) {
	
	int len = val.size();
	int ended = val.size() - 1;

	for (int i = 1; i <= len / 2; i++) {
		string first = val.substr(ended - i, i);
		string second = val.substr(ended, i);
		if (first.compare(second) == 0) return false;
		ended--;
		
	}
	return true;
}

void dfs(int cnt, string val) {
	if (ended == 1)
		return;
	if (!isValid(val))  return;
	if (cnt == n) {
		cout << val <<"\n";
		ended = 1;
		return;
	}

	dfs(cnt + 1, val + '1');

	dfs(cnt + 1, val + '2');

	dfs(cnt + 1, val + '3');

}
int main() {
	cin >> n;
	dfs(0, "");
}

 

dfs 함수입니다.

void dfs(int cnt, string val) {
	if (ended == 1)
		return;
	if (!isValid(val))  return;
	if (cnt == n) {
		cout << val <<"\n";
		ended = 1;
		return;
	}

	dfs(cnt + 1, val + '1');

	dfs(cnt + 1, val + '2');

	dfs(cnt + 1, val + '3');

}

보시는 것 처럼 전형적인 dfs 재귀 함수입니다. 

종료되는 시점은 cnt == n 일때 입니다. ( 1부터 2, 3번 순서로 탐색하기에 가장먼저 도착한 친구가 가장 값이 작습니다.)

하지만 추가된 ended == 1, isValid()  2조건이 포함되기때문에 백트래킹입니다.  ended는 출력초과를 막기위해 당연히 필요한 함수입니다. (겸사겸사 가지치기도 하게됩니다.)

그리고 isValid 함수를 통해서  해당 문자열이 유효한지 확인하고 유효할 경우에만 더 진행되는 구조입니다.

전형적인 백트래킹 문제였지만, 구현난이도가 낮지 않아서 저도 valid 함수에서 막혔던 문제입니다.

 

 

안보고 코드를 직접 입력하면서 꼭 손으로 풀어보세요!

 

반응형

'알고리즘 > DFS' 카테고리의 다른 글

[백준] 1062-가르침(C++)  (0) 2020.05.05
[백준] 1012-유기농 배추(C++)  (0) 2020.03.31
[백준] 15666-N과 M (12)(C++)  (0) 2020.03.25
[백준] 10026-적록색약(C++)  (0) 2020.03.12
[백준] 2668-숫자고르기(C++)  (0) 2020.03.11
반응형

문제링크:https://www.acmicpc.net/problem/15666

 

15666번: N과 M (12)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해야 한다.

www.acmicpc.net

 

dfs연습문제입니다. 

  • 같은 수를 여러 번 골라도 된다.
  • 고른 수열은 비내림차순이어야 한다

두가지 조건을 만족시켜야 합니다. 

중복 수를 제거하고 sort 함수를 통해 오름차순 배열로 정렬시켰습니다.

그 이후 재귀식을 통해서 count값을 올리며 진행했습니다. 

void dfs(int cnt) {
	if (cnt == m) {
		for (int i = 0; i < cnt; i++)
			cout << result[i] << ' ';
		cout << endl;
		return;
	}

	for (int i = 0; i < arr_index; i++) {
		bool jud = true;

		for (int j = 0; j < cnt; j++)
			if (result[j] > arr[i]) {
				jud = false;
				break;
			}


		if (jud == true)
		{
			result [cnt] = arr[i];
			dfs(cnt + 1);
		}
	}
}

위 처럼 구현하였습니다.

 

정답코드입니다.

#include <iostream>
#include <algorithm>
using namespace std;

int n = 0, m = 0,arr_index=0,num;
int arr[8] = { 0 };
int result[8];
bool visited[8] = { 0 };
void dfs(int cnt) {
	if (cnt == m) {
		for (int i = 0; i < cnt; i++)
			cout << result[i] << ' ';
		cout << endl;
		return;
	}

	for (int i = 0; i < arr_index; i++) {
		bool jud = true;

		for (int j = 0; j < cnt; j++)
			if (result[j] > arr[i]) {
				jud = false;
				break;
			}


		if (jud == true)
		{
			result [cnt] = arr[i];
			dfs(cnt + 1);
		}
	}
}
int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		bool jud = true;
		cin >> num;
		for (int j = 0; j < arr_index; j++) {
			if (arr[j] == num) {
				jud = false;
				break;
			}
		}
		if (jud == true)
			arr[arr_index++] = num;
	}
	sort(arr, arr + arr_index);
	
	dfs(0);
}

 

 

반응형

'알고리즘 > DFS' 카테고리의 다른 글

[백준] 1012-유기농 배추(C++)  (0) 2020.03.31
[백준] 2661-좋은수열(C++)  (0) 2020.03.30
[백준] 10026-적록색약(C++)  (0) 2020.03.12
[백준] 2668-숫자고르기(C++)  (0) 2020.03.11
[백준] 2583-영역구하기(C++)  (0) 2020.03.11
반응형

문제링크:https://www.acmicpc.net/problem/10026

 

10026번: 적록색약

문제 적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다. 크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록), B(파랑) 중 하나를 색칠한 그림이 있다. 그림은 몇 개의 구역으로 나뉘어져 있는데, 구역은 같은 색으로 이루어져 있다. 또, 같은 색상이 상하좌우로 인접해 있는 경우에 두 글자는 같은 구역에 속한다. (색상의 차이를 거의 느끼지 못하는 경우도 같은

www.acmicpc.net

 

dfs문제입니다. bfs로도 풀 수 있고 단순히 완전탐색을 하면서 갯수를 세어주면 되는 간단한 문제였습니다. 

방문했는지 여부와 같은색인지를 판별해서 탐색을 했습니다. bfs, dfs 모두 쉽게 구현가능하니까 직접 구현해보시면 좋을 것 같습니다.

 

 

너무쉬워서 설명은 생략하겠습니다. 

 

 

정답코드입니다. 화이팅 :)

#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int n = 0,normal =0,medicine=0;
string arr[100];
bool visited[101][101] = { 0 };
int dex[4] = { 1,-1,0,0 };
int dey[4] = { 0, 0,1,-1 };
void dfs(char color,int x,int y) {

	visited[y][x] = 1;
	
	for (int i = 0; i < 4; i++) {
		int yy = y + dey[i];
		int xx = x + dex[i];
		if (xx >= 0 && xx < n && yy >= 0 && yy< n)
			if (!visited[yy][xx] && arr[yy][xx] == color)
				dfs(color, xx, yy);
	}
}

int main() {
	cin >> n;

	for (int i = 0; i < n; i++)
		cin >> arr[i];

	for(int i=0;i<n;i++)
		for (int j = 0; j < arr[i].size(); j++) 
			if (!visited[i][j]) {
				dfs(arr[i][j], j, i);
				normal++;
			}

	memset(visited, 0, sizeof(visited));

	for (int i = 0; i<n; i++)
		for (int j = 0; j < arr[i].size(); j++) 
			if (arr[i][j] == 'R') arr[i][j] = 'G';

	for (int i = 0; i<n; i++)
		for (int j = 0; j < arr[i].size(); j++)
			if (!visited[i][j]) {
				dfs(arr[i][j], j, i);
				medicine++;
			}

	cout << normal << ' '<< medicine << endl;
	
}
반응형

'알고리즘 > DFS' 카테고리의 다른 글

[백준] 2661-좋은수열(C++)  (0) 2020.03.30
[백준] 15666-N과 M (12)(C++)  (0) 2020.03.25
[백준] 2668-숫자고르기(C++)  (0) 2020.03.11
[백준] 2583-영역구하기(C++)  (0) 2020.03.11
[백준] 11403-경로찾기(C++)  (0) 2020.03.07

+ Recent posts