Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

08 dfs bfs #9

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions 08_DFS_BFS/1325.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

vector<bool> hacked; // 컴퓨터 해킹 여부 저장

int dfs(int node, vector<vector<int>> &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<int> hack(int n, vector<vector<int>> &graph) { // 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터 번호 반환
int max_cnt = 0; // 감염된 컴퓨터 수의 최댓값
vector<int> 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<vector<int>> graph;

// 입력
cin >> n >> m;
graph.assign(n+1, vector<int> (0));//그래프 초기화하기
while(m--) {
/*
* a는 b를 신뢰한다
* == b는 a를 감염시킬 수 있다
*/
cin >> a >> b;//a와 b 입력받기
graph[b].push_back(a);//신뢰관계 그래프에 추가하기
}

// 연산 & 출력
vector<int> result = hack(n, graph);//연산하기
for(int i = 0; i < result.size(); i++) {//가장 많이 해킹할 수 있는 컴퓨터 번호 출력
cout << result[i] << ' ';
}
return 0;
}
75 changes: 75 additions & 0 deletions 08_DFS_BFS/2615.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// 2615번 오목: https://www.acmicpc.net/problem/2615
#include <iostream>
#include <vector>

using namespace std;

typedef vector<vector<int>> matrix;
const int SIZE = 20, EMPTY = 0;

// 방향에 따른 좌표 증가량
// 맨 왼쪽 위 돌을 기준으로 검사하기 때문에 오른쪽+아래쪽으로 향하는 방향만 정의
const vector<int> dx = {-1, 0, 1, 1};
const vector<int> 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<int>(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;
}
77 changes: 77 additions & 0 deletions 08_DFS_BFS/4963.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

typedef pair<int, int> 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<vector<int>> &map) { // bfs 탐색
queue<pi> 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<vector<int>> &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<vector<int>> map;

while(true) {
// 입력
cin >> w >> h;//너비와 높이 입력받기
if(w == 0 && h == 0) { // 종료조건
break;
}

map.assign(h, vector<int> (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;
}