BFS, DFS에 대해서는 이전 알고리즘 스터디에서 다뤘던 주제라서 안다.
BFS는 너비우선탐색이고 , 큐를 사용하는 방식이고 DFS는 깊이우선탐색에 스택을 사용한다 이정도??
근데 이거만 안다고 해서 문제가 풀리지는 않더라,,,,ㅜㅜ
개념 공부하고 관련 예제 풀어보고 알고리즘 공부할때마다 느끼는 건데 수능수학 공부하는 거 같다.
아래 블로그에서 기본 DFS,BFS에 해당하는 1-4 번 네가지 문제를 풀어보자.
백준 2606번 바이러스 (www.acmicpc.net/problem/2606)
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
vector<vector<int>> computers;
vector<bool>visited;
int n;
int bfs(int x){
queue<int>que;
que.push(x);
int num, cnt=0;
while (!que.empty()) {
num = que.front();
que.pop();
if (!visited[num]) {
visited[num] = true;
cnt++;
for (int i = 0; i < computers[num].size(); i++) que.push(computers[num][i]);
}
}
return cnt;
}
int main() {
int edges;
cin >> n >> edges;
//visited 초기화
computers.resize(n + 1);
visited.resize(n + 1);
//computers 그래프 초기화
for (int i = 0; i < edges; i++) {
int a, b;
cin >> a >> b;
computers[a].push_back(b);
computers[b].push_back(a);
}
cout << bfs(1)-1 << endl;
}
내 최애 유니온파인드도 가능할 거 같아서 해봄
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
vector<int>parent;
int n;
int getparents(int x) {
if (parent[x] == x) return x;
return parent[x] = getparents(parent[x]);
}
void unionparents(int x, int y) {
x = getparents(x);
y = getparents(y);
if (x > y) parent[x] = y;
else parent[y] = x;
}
bool find(int x, int y) {
x = getparents(x);
y = getparents(y);
if (x == y) return true;
return false;
}
int main() {
int edges;
cin >> n >> edges;
parent.resize(n + 1);
for (int i = 1; i <= n; i++) parent[i] = i;
for (int i = 0; i < edges; i++) {
int a, b;
cin >> a >> b;
unionparents(a, b);
}
int cnt = 0;
for (int i = 2; i <= n; i++) {
if (find(1, i)) cnt++;
}
cout << cnt;
}
백준 2667번 단지번호붙이기(www.acmicpc.net/problem/2667)
DFS 버전
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int home[25][25];
vector<int>house_number;
int n, cnt;
int dx[] = { -1,1,0,0 };
int dy[] = { 0,0,-1,1 };
void dfs(int x, int y ) {
if (x > -1 && x<n && y>-1 && y < n) {
if (home[x][y] == 1) {
home[x][y] = 0;
cnt++;
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
dfs(nx,ny);
}
}
}
}
int main() {
cin >> n;
for (int i = 0; i< n; i++) {
for (int j = 0; j < n; j++) scanf("%1d", &home[i][j]);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cnt = 0;
dfs(i, j);
if (cnt != 0) house_number.push_back(cnt);
}
}
sort(house_number.begin(), house_number.end());
cout << house_number.size() << endl;
for (int i = 0; i < house_number.size() ; i++) cout << house_number[i]<<endl;
}
BFS 버전
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
int home[25][25];
vector<int>house_number;
int n, cnt;
int dx[] = { -1,1,0,0 };
int dy[] = { 0,0,-1,1 };
void bfs(int i, int j) {
queue<pair<int, int>>que;
que.push({ i,j });
while (!que.empty()) {
int x = que.front().first;
int y = que.front().second;
que.pop();
if (x > -1 && x<n && y>-1 && y < n) {
if (home[x][y] == 1) {
home[x][y] = 0;
cnt++;
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
que.push({ nx, ny });
}
}
}
}
}
int main() {
cin >> n;
for (int i = 0; i< n; i++) {
for (int j = 0; j < n; j++) scanf("%1d", &home[i][j]);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cnt = 0;
bfs(i, j);
if (cnt != 0) house_number.push_back(cnt);
}
}
sort(house_number.begin(), house_number.end());
cout << house_number.size() << endl;
for (int i = 0; i < house_number.size() ; i++) cout << house_number[i]<<endl;
}
백준 2589번 보물섬(www.acmicpc.net/problem/2589)
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
vector<vector<int>>map;
queue<pair<int, int>> que;
int n, m , cnt , max = 0;
int dx[] = { -1,1,0,0 };
int dy[] = { 0,0,-1,1 };
int bfs(int first_x, int first_y) {
vector<vector<int>>visited;
visited.resize(n, vector<int>(m, 0));
que.push({ first_x, first_y });
visited[first_x][first_y] = 1;
int max_num = 0;
while (!que.empty()) {
int x = que.front().first;
int y = que.front().second;
que.pop();
cnt++;
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx > -1 && nx < n && ny >-1 && ny < m) {
if ((!visited[nx][ny]) && (map[nx][ny])) {
visited[nx][ny] = visited[x][y] + 1;
que.push({ nx,ny });
if (visited[nx][ny] > max_num) max_num = visited[nx][ny];
}
}
}
}
return max_num;
}
int main() {
cin >> n >> m;
map.resize(n, vector<int>(m, 0));
for (int i = 0; i < n; i++) {
string str;
cin >> str;
for (int j = 0; j < m; j++) {
char land = str[j];
if (land == 'W') map[i][j] = 0;
else map[i][j] = 1;
}
}
int max_path = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (map[i][j] == 1) {
int path = bfs(i, j);
if (path > max_path) max_path = path;
}
}
}
printf("%d", max_path-1);
}
로직이 맞았다고 생각하는데 자꾸 내가 원하는 답이 나오지 않아서 백준에 질문을 했다.
www.acmicpc.net/board/view/60143#post
resize(n, T)는 현재 벡터의 크기가 n보다 작을 때 늘어나는 공간을 T로 채워 주는 역할을 합니다.
따라서 17번째 줄은 bfs가 처음 호출될 때 단 한 번만 초기화를 하고, 그 뒤로는 아무 일도 하지 않습니다
resize(n,0) 을 해주면 매번 bfs가 실행될때마다 초기화가 되는 줄 알았는데 그게 아니었다 ㅜㅜㅜ
백준 토마토 7576번 (www.acmicpc.net/problem/7576)
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
int tomato[1005][1005];
int visited[1005][1005];
queue<pair<int, int>>que;
int n, m;
int dx[] = { -1,1,0,0 };
int dy[] = { 0,0,-1,1 };
int bfs() {
int max_day = 1;
while (!que.empty()) {
int x = que.front().first;
int y = que.front().second;
que.pop();
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx > m - 1 || ny <0 || ny > n - 1 || visited[nx][ny] || tomato[nx][ny]) continue;
que.push({ nx,ny });
visited[nx][ny] = visited[x][y] + 1;
if (max_day < visited[nx][ny]) max_day = visited[nx][ny];
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!visited[i][j] && !tomato[i][j]) return 0;
}
}
return max_day;
}
int main() {
cin >> n >> m; //열, 행
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cin >> tomato[i][j];
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (tomato[i][j] == 1) {
que.push({ i,j });
visited[i][j] = 1;
}
}
}
if (que.empty()) cout << -1;
else {
int max_day = bfs();
cout << max_day - 1;
}
}
토마토가 있는 좌표를 큐에 모두 넣어주고 이 좌표들에 대해서 모두 visited = 1 로 체크를 해준다.
그 후 좌표들을 빼서 상,하,좌,우 다음 칸으로 넘어갈떄마다 visited를 하나씩 추가해주었다.
bfs를 다 돌았을 때, 아직도 visited 체크가 안됐으면서 tomato 가 0인 곳이 존재한다면 -1을 반환
효율적인 코드인지는 모르겠지만 자신감이 아주 살짝 생겼다.
이제 알고리즘 숙제하러가보겠다 뿅-😎
'알고리즘 > 알고리즘 관련 메모장' 카테고리의 다른 글
DFS로 순열 및 조합 구현 (0) | 2020.12.17 |
---|---|
C++ 배열/벡터 copy 와 memset (0) | 2020.12.11 |
c++ 3일차 (0) | 2020.11.13 |
C++ string 사용법 (0) | 2020.11.09 |
C++ - 2일차 백준 단계별로 풀기 5~7단계 (0) | 2020.11.08 |