diff --git a/08_DFS_BFS/1325.cpp b/08_DFS_BFS/1325.cpp new file mode 100644 index 0000000..9679f2c --- /dev/null +++ b/08_DFS_BFS/1325.cpp @@ -0,0 +1,68 @@ +#include +#include +#include + +using namespace std; + +vector hacked; // 컴퓨터 해킹 여부 저장 + +int dfs(int node, vector> &graph) { // node 컴퓨터가 해킹할 수 있는 컴퓨터 개수 세기 + int cnt = 1; // node가 해킹할 수 있는 컴퓨터 수 + hacked[node] = true;//해킹됨 + + for(int i = 0; i < graph[node].size(); i++) { // node 컴퓨터가 해킹할 수 있는 컴퓨터 탐색 + int next_node = graph[node][i]; + if(!hacked[next_node]) { // 아직 해킹되지 않은 컴퓨터 발견 + cnt += dfs(next_node, graph);//해킹할 수 있는 컴퓨터 재귀적으로 더하기 + } + } + return cnt; +} + +vector hack(int n, vector> &graph) { // 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터 번호 반환 + int max_cnt = 0; // 감염된 컴퓨터 수의 최댓값 + vector result; // 컴퓨터 번호 저장 + + for(int i = 1; i <= n; i++) { // i : 최초로 해킹된 컴퓨터 + hacked.assign(n+1, false); // (탐색 시작전 전역변수 초기화 필요) + int tmp = dfs(i, graph); // tmp : i번 컴퓨터가 해킹한 컴퓨터 수 + + if(tmp > max_cnt) { // 최댓값 갱신 + max_cnt = tmp; + result = {i}; + } + else if(tmp == max_cnt) { // 컴퓨터 번호만 push + result.push_back(i); + } + } + return result; +} + +/* + * [가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터 번호 구하기] + * 그래프 탐색을 이용하여 컴퓨터별 해킹할 수 있는 컴퓨터 수를 구한다. +*/ + +int main() { + int n, m, a, b; + vector> graph; + + // 입력 + cin >> n >> m; + graph.assign(n+1, vector (0));//그래프 초기화하기 + while(m--) { + /* + * a는 b를 신뢰한다 + * == b는 a를 감염시킬 수 있다 + */ + cin >> a >> b;//a와 b 입력받기 + graph[b].push_back(a);//신뢰관계 그래프에 추가하기 + } + + // 연산 & 출력 + vector result = hack(n, graph);//연산하기 + for(int i = 0; i < result.size(); i++) {//가장 많이 해킹할 수 있는 컴퓨터 번호 출력 + cout << result[i] << ' '; + } + return 0; +} \ No newline at end of file diff --git a/08_DFS_BFS/2615.cpp b/08_DFS_BFS/2615.cpp new file mode 100644 index 0000000..39b05bc --- /dev/null +++ b/08_DFS_BFS/2615.cpp @@ -0,0 +1,75 @@ +// 2615번 오목: https://www.acmicpc.net/problem/2615 +#include +#include + +using namespace std; + +typedef vector> matrix; +const int SIZE = 20, EMPTY = 0; + +// 방향에 따른 좌표 증가량 +// 맨 왼쪽 위 돌을 기준으로 검사하기 때문에 오른쪽+아래쪽으로 향하는 방향만 정의 +const vector dx = {-1, 0, 1, 1}; +const vector dy = {1, 1, 1, 0}; + +/** + * 범위와 돌의 종류가 유효한지 확인한다. +*/ +bool isValid(matrix &board, int x, int y, int color) { + return (x > 0 && x < SIZE && y > 0 && y < SIZE && board[x][y] == color);//범위와 돌의 종류가 유효한지 확인한다. +} + +/** + * 해당 좌표(x, y)부터 연속적으로 5알이 놓이는지 확인한다. +*/ +bool checkWin(matrix &board, int x, int y) { + int color = board[x][y]; // 기준 색 + + // 4 방향에 대해 검사 + for (int idx = 0; idx < 4; idx++) { + int cnt = 1; // cnt: 같은 방향에 놓인 같은 색 돌의 수 + int prev_x = x - dx[idx], prev_y = y - dy[idx];//이전 x 이전 y + int next_x = x + dx[idx], next_y = y + dy[idx];//다음 x 다음 y + + // 같은 방향에서 그 이전에도 같은 색 돌이 있었다면 패스 (-> 여섯 알 이상 놓이는 경우를 제외하기 위함) + if (isValid(board, prev_x, prev_y, color)) { + continue; + } + + // 연속적으로 놓인 5알이 같은 색인지 확인 + while (isValid(board, next_x, next_y, color) && cnt < 6) { + next_x += dx[idx]; + next_y += dy[idx]; + cnt++; + } + // cnt가 5일 때만 true 리턴 (-> 다섯 알보다 적거나 다섯 알보다 많이 놓이는 경우를 제외) + if (cnt == 5) { + return true; + } + } + return false; +} + +int main() { + // 입력 + matrix board(SIZE, vector(SIZE, 0)); // 바둑판 + for (int i = 1; i < SIZE; i++) + for (int j = 1; j < SIZE; j++) + cin >> board[i][j];//각줄의 바둑돌 입력하기 + + // 연산 및 출력 + for (int y = 1; y < SIZE; y++) { + for (int x = 1; x < SIZE; x++) { + // 빈 칸이면 패스 + if (board[x][y] == EMPTY) { + continue; + } + if (checkWin(board, x, y)) {// 해당 좌표(x, y)부터 연속적으로 5알이 놓였다면 정답 출력 + cout << board[x][y] << '\n' + << x << ' ' << y; + return 0; + } + } + } + cout << 0; +} \ No newline at end of file diff --git a/08_DFS_BFS/4963.cpp b/08_DFS_BFS/4963.cpp new file mode 100644 index 0000000..e722fb2 --- /dev/null +++ b/08_DFS_BFS/4963.cpp @@ -0,0 +1,77 @@ +#include +#include +#include + +using namespace std; + +typedef pair pi; + +const int VISITED = 2; +int dr[8] = {-1, -1, 0, 1, 1, 1, 0, -1}; +int dc[8] = {0, 1, 1, 1, 0, -1, -1, -1}; + +void bfs(int sr, int sc, int h, int w, vector> &map) { // bfs 탐색 + queue q; + + q.push({sr, sc});//위치 삽입하기 + map[sr][sc] = VISITED; // 방문 check + + while(!q.empty()) { + int r = q.front().first; + int c = q.front().second; + q.pop(); + + for(int i = 0; i < 8; i++) { // 이어진 땅 없는지 탐색 + int nr = r + dr[i]; + int nc = c + dc[i]; + + if(nr >= 0 && nr < h && nc >= 0 && nc < w && map[nr][nc] == 1) { // 땅 발견 + q.push({nr, nc});//이어진 땅 중 땅 발견하면 삽입 + map[nr][nc] = VISITED; // 방문 check + } + } + } +} + +int cntIsland(int h, int w, vector> &map) { // 섬 개수 세기 + int cnt = 0;//섬개수 + for(int i = 0; i < h; i++) {//높이랑 + for(int j = 0; j < w; j++) {//넓이 만큼 반복 + if(map[i][j] == 1) { // 땅 발견 + cnt++;//섬 개수 + 1 + bfs(i, j, h, w, map); // (i,j)와 연결된 땅 탐색 (== 섬 만들기) + } + } + } + return cnt; +} + +/* + * [섬의 개수 세기] + * 1. 땅을 발견할 때마다 그래프 탐색을 이용하여 연결된 땅을 찾아 섬을 만든다. + * 2. 따라서 그래프 탐색 횟수가 섬의 개수가 된다. +*/ + +int main() { + int w, h; + vector> map; + + while(true) { + // 입력 + cin >> w >> h;//너비와 높이 입력받기 + if(w == 0 && h == 0) { // 종료조건 + break; + } + + map.assign(h, vector (w, 0));//map 초기화 + for(int i = 0; i < h; i++) { + for(int j = 0; j < w; j++) { + cin >> map[i][j];//땅 바다 입력받기 + } + } + + // 연산 & 출력 + cout << cntIsland(h, w, map) << '\n'; + } + return 0; +} \ No newline at end of file