Skip to content
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
67 changes: 67 additions & 0 deletions 08_DFS_BFS/1325.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>

using namespace std;

vector<vector<int>> adj_list;
vector<bool> visited;
int n;

int dfs(int start) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 문제는 BFS로는 쓸 수 없을까요? 가능하다면 한번 작성해보세요! DFS 함수도 재귀를 이용해서 구현해보셔도 도움이 많이 될 것 같습니다! 재귀가 많이 쓰인답니다.

stack<int> s;
s.push(start);
visited[start] = true;
int nodes_visited = 1;

while (!s.empty()) {
int node = s.top();
s.pop();

for (int neighbor : adj_list[node]) {
if (!visited[neighbor]) {
s.push(neighbor);
visited[neighbor] = true;
nodes_visited++;
}
}
}

return nodes_visited;
}

int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);

int m;
cin >> n >> m;
adj_list.resize(n + 1);
visited.assign(n + 1, false);

while (m--) {
int a, b;
cin >> a >> b;
adj_list[b].push_back(a); // 역방향 그래프를 만듭니다.
}

vector<int> result(n + 1, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

n+1로 초기화해주시는 것 좋습니다!


for (int v = 1; v <= n; v++) {
fill(visited.begin(), visited.end(), false); // visited 배열 초기화
int nodes_visited = dfs(v);
result[v] = nodes_visited;
}

int max_hacked = *max_element(result.begin(), result.end());

for (int i = 1; i <= n; i++) {
if (result[i] == max_hacked) {
cout << i << " ";
}
}

return 0;
}
75 changes: 75 additions & 0 deletions 08_DFS_BFS/19538.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import java.io.*;
import java.util.*;

public class Main {

public static int[] solution(int N, int[][] adj, int M, int[] firstInfected) {
Queue<Integer> Q = new ArrayDeque<>(); // 감염된 사람의 번호를 큐에 저장할 것이다.
int[] answer = new int[N + 1]; // solution 함수에서 리턴할 배열
Arrays.fill(answer, -1); // 사이즈 N+1, -1로 초기화
int[] turn = new int[N + 1]; // 감염까지 남은 주변 비감염 사람 수
Arrays.fill(turn, 0); // 사이즈 N+1, 0로 초기화

// 최조생성자 처리
for (int t : firstInfected) {
Q.add(t); // 최조생성자는 감염된 사람이고 주변인에게 영향을 주므로 큐에 넣어주고
answer[t] = 0; // 0분에 감염되었음을 저장한다.
}

// 주변인의 절반 이상이 루머를 믿을 때 본인도 루머를 믿으므로
// 몇 명이 감염되었을 때 자신이 감염되는지에 대한 정보를
// 사람 i의 주변인물 수 + 1 / 2의 몫으로 저장해둔다.
// 사람의 번호가 아닌 입력의 끝을 말하는 0이 adj 배열에 포함되어 있으므로 + 1은 안해도 된다.
for (int i = 1; i <= N; i++)
turn[i] = adj[i].length / 2;

while (!Q.isEmpty()) { // 큐가 빌 때까지 탐색하는데, 큐가 비었다면 모든 탐색을 마쳤다는 의미이다.
int current = Q.poll(); // 현재, 가장 먼저 감염된 사람의

for (Integer next : adj[current]) { // 주변인물들에게
if (next == 0) break;
turn[next] -= 1; // 자신(주변인물)이 감염되기까지 남은 사람 수를 1 빼고
if (answer[next] == -1 && turn[next] <= 0) { // 만약 아직 감염되지 않았고 주변인의 반 이상이 감염되었다면
Q.add(next); // 감염되었기에 큐에 자신의 번호를 넣어주고
answer[next] = answer[current] + 1; // 자신을 감염시킨 마지막 주변인의 감염된 시간 + 1분을 더해 저장한다.
}
}
}

// 계산의 편의를 위해 배열에 0번 index가 아닌 1번 index부터 정답이 저장되었으므로,
// 배열을 두번째 원소부터 잘라 반환한다.
return Arrays.copyOfRange(answer, 1, answer.length);
}

public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuilder sb = new StringBuilder();

int N = Integer.parseInt(br.readLine());
int[][] adj = new int[N+1][];
adj[0] = new int[]{0};
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
List<Integer> arrayList = new ArrayList<>();
while (true) {
int temp = Integer.parseInt(st.nextToken());
arrayList.add(temp);
if (temp == 0) {
adj[i] = arrayList.stream().mapToInt(Integer::intValue).toArray();
break;
}
}
}

int M = Integer.parseInt(br.readLine());
int[] firstInfected = new int[M];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < M; i++) {
int temp = Integer.parseInt(st.nextToken());
firstInfected[i] = temp;
}
Arrays.stream(solution(N, adj, M, firstInfected)).forEach(t -> sb.append(t).append(" "));
System.out.println(sb);
}
}
55 changes: 55 additions & 0 deletions 08_DFS_BFS/2615.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Copy link

@mingulmangul mingulmangul Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1. 자바에서는 입력에 BufferedReader, InputStreamReader를 사용하면 훨씬 빨라요! Scanner는 꽤 속도가 느린 편이라 잘 사용하지 않는다고 해요. 코드에 문제가 있는 건 아니지만 혹시 자바로 코딩테스트를 보실 예정이라면 꼭 알아두시면 좋을 라이브러리라 P1으로 코멘트 남겨드립니다 ㅎㅎ


int[][] graph = new int[19][19];
int[] dx = {0, 1, 1, -1};
int[] dy = {1, 0, 1, 1};

for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
graph[i][j] = sc.nextInt();
}
}
Comment on lines +7 to +15

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2. 여기 반복해서 사용되는 숫자가 있네요! 자주 사용되는 숫자를 하드코딩하다 보면 실수할 가능성도 높아지기 때문에 따로 상수로 선언해준 뒤에 사용하는 것이 좋습니다 🤗 코드의 가독성이나 유지보수 측면에서도 좋아요!


for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
if (graph[i][j] != 0) {
int target = graph[i][j];

for (int k = 0; k < 4; k++) {
int cnt = 1;
int nx = i + dx[k];
int ny = j + dy[k];

while (0 <= nx && nx < 19 && 0 <= ny && ny < 19 && graph[nx][ny] == target) {
cnt++;

if (cnt == 5) {
if (0 <= i - dx[k] && i - dx[k] < 19 && 0 <= j - dy[k] && j - dy[k] < 19 &&
graph[i - dx[k]][j - dy[k]] == target) {
break;
}
if (0 <= nx + dx[k] && nx + dx[k] < 19 && 0 <= ny + dy[k] && ny + dy[k] < 19 &&
graph[nx + dx[k]][ny + dy[k]] == target) {
break;
}
Comment on lines +27 to +38

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2. 인덱스가 바둑판의 범위 내에 위치하는지, 그리고 해당 위치가 target과 같은 색인지 체크하는 조건이 계속 반복되네요! 반복되는 코드는 따로 메소드로 분리하면 코드의 의미도 더 명확해지고, 코드의 양이 줄어서 읽기도 더 쉬워질 것 같아요!


System.out.println(target);
System.out.println(i + 1 + " " + (j + 1));
System.exit(0);
}

nx += dx[k];
ny += dy[k];
}
}
}
Comment on lines +19 to +49

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2. 이 부분 인덴테이션이 꽤 깊네요..! 인덴테이션은 보통 3 뎁스를 넘지 않도록 얕게 유지하는게 좋습니다. 맨 처음 if문을 조건에 맞지 않는 경우로 바꾸면 continue를 사용해서 바로 다음 반복으로 넘어갈 수 있어요! 이러면 현재 if문 안에 있는 코드들은 if문 밖에서 작성해도 되기 때문에 인덴테이션도 한 단계 줄일 수 있어요. 그리고 인덴테이션이 깊어지거나 한 메소드가 길어지면, 적절하게 기능을 나눠서 메소드로 분리하는게 좋습니다! 하나의 메소드는 하나의 역할만 수행하는게 객체지향설계의 핵심이에요 ☺️

}
}

System.out.println(0);
}
}
60 changes: 60 additions & 0 deletions 08_DFS_BFS/4963.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {
public static void bfs(int x, int y, int[][] field) {
int[] dx = {1, -1, 0, 0, 1, -1, 1, -1};
int[] dy = {0, 0, -1, 1, -1, 1, 1, -1};
Comment on lines +7 to +8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8방향 탐색용 배열 두 개 선언 스킬 사용해주신 점 좋습니다!

field[x][y] = 0;
Queue<int[]> q = new LinkedList<>();
q.add(new int[]{x, y});

while (!q.isEmpty()) {
int[] current = q.poll();
int a = current[0];
int b = current[1];

for (int i = 0; i < 8; i++) {
int nx = a + dx[i];
int ny = b + dy[i];
if (0 <= nx && nx < field.length && 0 <= ny && ny < field[0].length && field[nx][ny] == 1) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

범위 체크 부분이 길어질 떄(체크해야 할 범위가 많거나 변수가 너무 많을 떄) 해당 검사 체크 부분만 함수로 뺴서 다루셔도 됩니다!

field[nx][ny] = 0;
q.add(new int[]{nx, ny});
}
}
}
}

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scanner보다 BufferedReader가 시간복잡도상 더 좋습니다!


while (true) {
int w = scanner.nextInt();
int h = scanner.nextInt();
if (w == 0 && h == 0) {
break;
}

int[][] field = new int[h][w];
int count = 0;

for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
field[i][j] = scanner.nextInt();
}
}

for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
if (field[i][j] == 1) {
bfs(i, j, field);
count++;
}
}
}

System.out.println(count);
}
}
}
55 changes: 55 additions & 0 deletions 08_DFS_BFS/게임맵최단거리.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include <vector>
#include <queue>
using namespace std;

struct Pos {
int x;
int y;
Pos(int _y, int _x) : y(_y), x(_x) {}
};

int solution(vector<vector<int> > maps) {
const int n = maps.size(); // 행의 개수
const int m = maps[0].size(); // 열의 개수
// 방향 (상, 우, 하, 좌)
int deltaY[4] = { -1, 0, 1, 0 };
int deltaX[4] = { 0, 1, 0, -1 };

vector<vector<int>> dist(n, vector<int>(m, -1)); // 출발지로부터 해당 위치까지의 최단 거리
queue<Pos> q; // 큐

// 출발지는 예약 작업을 할 수 없고 바로 방문해야 하니 미리 작업
q.push(Pos(0, 0)); // 큐에 출발지 좌표를 넣어 시작
dist[0][0] = 1; // 출발지의 거리는 1

while (!q.empty()) {
// 방문할 위치를 큐에서 꺼냄
Pos pos = q.front();
q.pop();
int nowY = pos.y;
int nowX = pos.x;

// 상, 우, 하, 좌 방향을 탐색
for (int i = 0; i < 4; ++i) {
int nextY = nowY + deltaY[i];
int nextX = nowX + deltaX[i];

// 다음에 방문할 수 있는지 체크
if (nextY < 0 || nextY >= n || nextX < 0 || nextX >= m) // 맵을 벗어난다면 예약할 수 없는 방향
continue;
if (maps[nextY][nextX] == 0) // 벽이라면 예약할 수 없는 방향
continue;
if (dist[nextY][nextX] != -1) // 이미 최단거리가 업데이트되었다면 스킵
continue;

// 다음에 방문할 수 있는 곳이니 큐에 넣어 예약하고, 그와 동시에 최단거리 업데이트
q.push(Pos(nextY, nextX));
dist[nextY][nextX] = dist[nowY][nowX] + 1; // 최단 거리 업데이트 (방문 노드에서 +1 하면 최단 거리)
}
}

if (dist[n - 1][m - 1] == -1) // 도착지까지 도달할 수 없는 경우
return -1;
else
return dist[n - 1][m - 1]; // 도착지의 최단거리 리턴
}
56 changes: 56 additions & 0 deletions end
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
commit c75e1fae1ade668b71a93161c3a7df4b882d3ed9 (HEAD -> 08_DFS_BFS, origin/main, origin/HEAD, main)
Merge: 1ab1b97 04b70a4
Author: somsom <72211340+kimeunsom@users.noreply.github.com>
Date: Tue Sep 19 14:38:50 2023 +0900

Merge pull request #3 from Altu-Bitu-5/04_브루트포스

[브루트포스] 9월 19일

commit 04b70a4979c90ba8f96bcb902419e644b855a832 (origin/04_브루트포스)
Author: unknown <somi5488@naver.com>
Date: Tue Sep 19 01:37:49 2023 +0900

[브루트포스] 9월 18일

commit 637350e790803c319294f7b8fe9cf84e01df6340
Author: unknown <somi5488@naver.com>
Date: Wed Sep 13 18:51:29 2023 +0900

[브루트포스] 9월 13일

commit 46dd74773d131d58d33164c9d36b9d7a0bf2e838 (origin/03_정수론)
Author: unknown <somi5488@naver.com>
Date: Wed Sep 6 18:35:34 2023 +0900

[정수론] 9월 6일

commit 0a50faf95aa260e4435bb37b9c41dd7652b25e82
Author: unknown <somi5488@naver.com>
Date: Wed Sep 6 16:23:30 2023 +0900

[정수론] 9월 6일

commit 050c8cffe428a01cf15880c3c17e3ffeb0d157fe (origin/01_정렬_맵_셋)
Author: unknown <somi5488@naver.com>
Date: Thu Aug 24 21:26:43 2023 +0900

[정렬, 맵, 셋] 8월 24일

commit 10fc0751b32a2f2a655033b37547b798e51ecdbe
Author: unknown <somi5488@naver.com>
Date: Wed Aug 23 11:37:08 2023 +0900

[정렬, 맵, 셋] 8월 23일

commit 6556d47ec0d698163ec2c9aa4932a56d0a4b1690
Author: unknown <somi5488@naver.com>
Date: Wed Aug 23 11:27:10 2023 +0900

[정렬, 맵, 셋] 8월 23일

commit 1ab1b97a09888af0e348e3d3fa6bb612f59855bc
Author: somsom <72211340+kimeunsom@users.noreply.github.com>
Date: Tue Aug 22 19:11:09 2023 +0900

Initial commit