diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/README.md" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/README.md" index 9d54f6c2..ccb01fe4 100644 --- "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/README.md" +++ "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/README.md" @@ -23,16 +23,16 @@ | 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | | :-----------------------------------------------------------------------: | :------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :------------------------: | -| 14503 | 로봇 청소기 | | [C++]() | 구현, 시뮬레이션 | -| 20922 | 겹치는 건 싫어 | | [C++]() | 투 포인터 | -| 20437 | 문자열 게임 2 | | [C++]() | 슬라이딩 윈도우 | +| 14503 | 로봇 청소기 | | [C++_v1](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/11_%ED%88%AC%20%ED%8F%AC%EC%9D%B8%ED%84%B0/%ED%95%84%EC%88%98/14503_v1.cpp)
[C++_v2](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/11_%ED%88%AC%20%ED%8F%AC%EC%9D%B8%ED%84%B0/%ED%95%84%EC%88%98/14503_v2.cpp) | 구현, 시뮬레이션 | +| 20922 | 겹치는 건 싫어 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/11_%ED%88%AC%20%ED%8F%AC%EC%9D%B8%ED%84%B0/%ED%95%84%EC%88%98/20922.cpp) | 투 포인터 | +| 20437 | 문자열 게임 2 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/11_%ED%88%AC%20%ED%8F%AC%EC%9D%B8%ED%84%B0/%ED%95%84%EC%88%98/20437.cpp) | 슬라이딩 윈도우 | ### 도전 | 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | | :--------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :--: | -| 13422 | 도둑 | | [C++]() | 투 포인터, 슬라이딩 윈도우 | -| 2473 | 세 용액 | | [C++]() | 투 포인터 | +| 13422 | 도둑 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/11_%ED%88%AC%20%ED%8F%AC%EC%9D%B8%ED%84%B0/%EB%8F%84%EC%A0%84/13422.cpp) | 투 포인터, 슬라이딩 윈도우 | +| 2473 | 세 용액 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/11_%ED%88%AC%20%ED%8F%AC%EC%9D%B8%ED%84%B0/%EB%8F%84%EC%A0%84/2473.cpp) | 투 포인터 | --- ### 힌트 diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\217\204\354\240\204/13422.cpp" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\217\204\354\240\204/13422.cpp" new file mode 100644 index 00000000..204ba829 --- /dev/null +++ "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\217\204\354\240\204/13422.cpp" @@ -0,0 +1,51 @@ +#include +#include +using namespace std; + +/**m개의 집에서 k보다 작은 돈을 훔칠 수 있는 경우의 수 구하기*/ +int steal(vector house, int n, int m, int k) { + int ans = 0; // 훔칠 수 있는 가짓수 + int total = 0; // 현재 도둑질한 돈 + int left = 0, right = m - 1; + + for(int i = left; i <= right; i++) { + total += house[i]; + } + if(n == m) { // 모든 집을 훔쳐야하는 경우 -> 즉시 리턴 + return total < k; + } + + while(left != n) { // 슬라이딩 윈도우 + if(total < k) { // 도둑질한 돈이 k보다 작으면 훔칠 수 있음 + ans++; + } + total -= house[left++]; + right = (right+1) % n; + total += house[right]; + } + return ans; +} +/**[백준 13422: 도둑] + * 1. 윈도우의 크기를 m으로 설정하고, 윈도우를 시계방향으로 움직이면서 도둑질할 수 있는 돈 계산 + * 2. right는 left보다 m만큼 떨어지는 집으로 설정하면, 마을이 원 모양으로 생겼으므로 right가 인덱스 범위를 벗어날 수 있음! + * -> right = (left + m)이 아닌 right = (left + m) % n + * 3. (주의) n == m인 경우, 모든 집을 훔쳐야 하므로 슬라이딩 윈도우로 탐색하지 않고 바로 현재 값 리턴 +*/ +int main() { + int t, n, m, k; + vector house; + + // 입력 + cin >> t; + while (t--) { + cin >> n >> m >> k; + house.assign(n, 0); + for (int i = 0; i < n; i++) { + cin >> house[i]; + } + + // 연산 & 출력 + cout << steal(house, n, m, k) << "\n"; + } + return 0; +} \ No newline at end of file diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\217\204\354\240\204/2473.cpp" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\217\204\354\240\204/2473.cpp" new file mode 100644 index 00000000..a3b6ccc9 --- /dev/null +++ "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\217\204\354\240\204/2473.cpp" @@ -0,0 +1,64 @@ +#include +#include +#include +#include // abs() +#include // sort() + +#define INF 3 * 1e9 + 1 +typedef long long ll; +using namespace std; + +/**투 포인로 세 용액의 합이 가장 0에 가까운 용액 튜플 리턴*/ +tuple calSum(vector liquid) { + ll min_value = INF; + tuple ans; + + // 세 용액 중 하나(i)를 고정하고 나머지 두 용액에 해당될 용액 쌍을 투포인터로 탐색 + for (int i = 0; i < liquid.size() - 2; i++) { + // 포인터 초기화 + int left = i + 1; // 두 번째 용액 + int right = liquid.size() - 1; // 세 번째 용액 + // left는 항상 right보다 작아야 함 + while (left < right) { + ll value = liquid[i] + liquid[left] + liquid[right]; // 현재 세 용액의 합 + if (abs(value) < min_value) { + min_value = abs(value); + ans = {liquid[i], liquid[left], liquid[right]}; + } + if (value < 0) { // 현재 값이 0보다 작으면 더 큰 값을 만들어야 함 -> left++ + left++; + } else if (value > 0) { // 현재 값이 0보다 크다면 더 작은 값을 만들어야 함 -> right-- + right--; + } else { // 현재 값이 0이면 이보다 더 0보다 가까운 값은 존재하지 않으므로 탐색 종료 + return ans; + } + } + } + return ans; +} +/**[백준 2473: 세 용액] + * 1. 합이 가장 0에 가까운 세 용액의 인덱스를 각각 i, left, right로 설정 + * 2. i는 고정하고, left와 right로 투포인터를 이용해 탐색 + * 3. 현재 세 용액의 합이 0보다 작으면 left++ + * 4. 현재 세 용액의 합이 0보다 크면 right++ + * 5. 현재 세 용액의 합이 0이면 이보다 더 0에 가까운 값은 존재하지 않으므로 탐색 종료 +*/ +int main() { + int n; + vector liquid; + + // 입력 + cin >> n; + liquid.assign(n, 0); + for (int i = 0; i < n; i++) { + cin >> liquid[i]; + } + + // 연산 + sort(liquid.begin(), liquid.end()); + tuple ans = calSum(liquid); + + // 출력 + cout << get<0>(ans) << " " << get<1>(ans) << " " << get<2>(ans); + return 0; +} \ No newline at end of file diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\217\204\354\240\204/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\217\204\354\240\204/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" deleted file mode 100644 index e69de29b..00000000 diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/14503_v1.cpp" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/14503_v1.cpp" new file mode 100644 index 00000000..83d3857b --- /dev/null +++ "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/14503_v1.cpp" @@ -0,0 +1,74 @@ +#include + +using namespace std; + +const int SIZE = 50; +const int CLEAN = 2; +int n, m, cnt = 0; // 세로 크기, 가로 크기, 청소한 칸 개수 + +int board[SIZE][SIZE]; // (0: 빈 칸, 1: 벽, 2: 청소 완료) +int dx[4] = {0, 1, 0, -1}, dy[4] = {-1, 0, 1, 0}; // 북 동 남 서 + +void dfs(int row, int col, int dir) { + // 1. 현재 위치 청소 + if(board[row][col] != CLEAN) { + cnt++; + } + board[row][col] = CLEAN; + + // [현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는가] + // 3. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우 + for(int i = 0; i < 4; i++) { // 3-1. 반시계 방향으로 90º 회전 + int new_dir = (dir-i+3) % 4; + int new_row = row + dy[new_dir], new_col = col + dx[new_dir]; + + if(board[new_row][new_col] == 0) { // 3-2. 아직 청소되지 않은 빈 칸 발견 + dfs(new_row, new_col, new_dir); // 한 칸 전진 + return; + } + } + + // 2. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우 + int back_dir = (dir+2) % 4; + int back_row = row + dy[back_dir], back_col = col + dx[back_dir]; + + // [바라보는 방향을 유지한 채로 한 칸 후진할 수 있는가] + // 2-2. 뒤쪽 칸이 벽이라 후진할 수 없는 경우 + if(board[back_row][back_col] == 1) { + return; + } + // 2-1. 바라보는 방향을 유지한 채로 한 칸 후진 + dfs(back_row, back_col, dir); // 방향 유지한 상태로 후진 (2-3) + return; +} + +/* + * [로봇 청소기 작동] + * 1. 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다. + * 2. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우, + * 2-1. 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다. + * 2-2. 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다. + * 3. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우, + * 3-1. 반시계 방향으로 90º 회전한다. + * 3-2. 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다. + * 3-3. 1번으로 돌아간다. +*/ + +int main() { + int r, c, d; // 로봇 청소기 정보 + + // 입력 + cin >> n >> m; + cin >> r >> c >> d; + + for(int i = 0; i < n; i++) { + for(int j = 0; j < m; j++) { + cin >> board[i][j]; + } + } + + // 연산 & 출력 + dfs(r, c, d); + cout << cnt; + return 0; +} \ No newline at end of file diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/14503_v2.cpp" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/14503_v2.cpp" new file mode 100644 index 00000000..5143611e --- /dev/null +++ "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/14503_v2.cpp" @@ -0,0 +1,79 @@ +#include +#include + +using namespace std; + +const int CLEAN = 2; + +int dx[4] = {0, 1, 0, -1}, dy[4] = {-1, 0, 1, 0}; // 북 동 남 서 + +int clean(int n, int m, int r, int c, int d, vector> &board) { + int cnt = 0; + + while(true) { + // 1. 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다. + if(board[r][c] != CLEAN) { + cnt++; + } + board[r][c] = CLEAN; + + bool find = false; // 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는가 + for(int i = 0; i < 4; i++) { + int nd = (d-i+3) % 4; + int nr = r + dy[nd], nc = c + dx[nd]; + + if(board[nr][nc] == 0) { // 3-2. 아직 청소되지 않은 빈 칸 발견 + find = true; + r = nr; c = nc; d = nd; + break; + } + } + if(find) { // 3. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우 1번으로 돌아감 + continue; + } + + // 2. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우 + int bd = (d+2) % 4; + int br = r + dy[bd], bc = c + dx[bd]; + + // [바라보는 방향을 유지한 채로 한 칸 후진할 수 있는가] + // 2-2. 뒤쪽 칸이 벽이라 후진할 수 없는 경우 + if(board[br][bc] == 1) { + return cnt; + } + // 2-1. 바라보는 방향을 유지한 채로 한 칸 후진 + r = br; c = bc; + } + return cnt; +} + +/* + * [로봇 청소기 작동] + * 1. 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다. + * 2. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우, + * 2-1. 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다. + * 2-2. 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다. + * 3. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우, + * 3-1. 반시계 방향으로 90º 회전한다. + * 3-2. 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다. + * 3-3. 1번으로 돌아간다. +*/ + +int main() { + int n, m, r, c, d; + vector> board; + + // 입력 + cin >> n >> m; + cin >> r >> c >> d; + board.assign(n, vector (m, 0)); + for(int i = 0; i < n; i++) { + for(int j = 0; j < m; j++) { + cin >> board[i][j]; + } + } + + // 연산 & 출력 + cout << clean(n, m, r, c, d, board); + return 0; +} \ No newline at end of file diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/20437.cpp" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/20437.cpp" index 442dc181..92549d7a 100644 --- "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/20437.cpp" +++ "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/20437.cpp" @@ -1,3 +1,62 @@ + +#include +#include +#include + +using namespace std; +typedef pair ci; +const int MAX_ALPHA = 26; // 알파벳 개수 + +/**문자를 k개 포함하는 가장 짧은 문자열과 가장 긴 문자열의 쌍 구하기*/ +ci solution(string w, int k) { + vector> char_idx(MAX_ALPHA); + int min_len = w.size(); // 가장 짧은 문자열 길이 초기화 + int max_len = -1; // 가장 긴 문자열 길이 초기화 + + for (int i = 0; i < w.size(); i++) { + char_idx[w[i] - 'a'].push_back(i); // 문자의 인덱스 저장 + } + + for (int i = 0; i < MAX_ALPHA; i++) { // 각 문자를 포함하는 문자열 확인 + if (char_idx[i].size() < k) { // 해당 알파벳이 k번 이상 등장하지 않으면 탐색 X + continue; + } + int left = 0, right = k - 1; // 포인터 초기화 + while (right < char_idx[i].size()) { + int tmp_len = char_idx[i][right] - char_idx[i][left] + 1; + min_len = min(min_len, tmp_len); + max_len = max(max_len, tmp_len); + left++; // 윈도우 이동 + right++; + } + } + return {min_len, max_len}; +} +/**[백준 20437: 문자열 게임2] + * 1. 각 알파벳의 위치 인덱스를 char_idx에 저장 + * 2. 윈도우의 크기를 k로 설정하고 윈도우를 오른쪽으로 이동시키며 + * 가장 짧은 문자열과 가장 긴 문자열 탐색 + * 이때 각 문자열의 길이는 char_idx[i][right] - char_idx[i][left] + 1 +*/ +int main() { + int t, k; + string w; + + // 입력 + cin >> t; + + while (t--) { + cin >> w >> k; + + // 연산 + ci ans = solution(w, k); + + // 출력 + if (ans.second == -1) { + cout << -1 << "\n"; + } else { + cout << ans.first << " " << ans.second << "\n"; +======= #include #include #include @@ -52,6 +111,7 @@ int main() { } else { cout << min_length << " " << max_length << "\n"; //문자열을 찾은 경우->출력 + } } return 0; diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/20922.cpp" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/20922.cpp" index 61aa096b..28daa3ba 100644 --- "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/20922.cpp" +++ "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/20922.cpp" @@ -1,3 +1,50 @@ + +#include +#include +#include + +using namespace std; +const int MAX_NUM = 100001; //수열 내 숫자 최대값 + +/**같은 정수를 k개 이하로 포함하는 최장 연속 부분 수열 길이 구하기*/ +int getMaxLen(vector &number, int n, int k) { + vector count(MAX_NUM, 0); // 수열 내 각 숫자의 개수 저장 + int left = 0, right = 0; // 포인터 초기화 + int max_len = 0; // 최대 수열 길이 초기화 + + while (right < n) { + // right를 오른쪽으로 옮겨가면서 right번째 숫자를 수열에 추가할 수 있을 지 판단 + if (count[number[right]] >= k) { // right에 있는 숫자의 개수가 k가 넘으면 -> 추가 불가 + count[number[left]]--; // left 숫자 삭제 + left++; + } else { // right에 있는 숫자의 개수가 k보다 작으면 -> 추가 가능 + count[number[right]]++; // right 숫자 추가 + right++; + max_len = max(max_len, right - left); // 최대 수열 길이 갱신 + } + } + return max_len; +} +/**[백준 20922: 겹치는 건 싫어] + * 1. 맨 왼쪽부터 투포인터를 이용해 탐색하며 left와 right 사이에 있는 숫자들의 개수를 count에 저장 + * 2. 오른쪽에 있는 숫자를 수열에 추가할 수 있으면 추가하고 right++ + * 3. 오른쪽에 있는 숫자를 수열에 추가할 수 없으면 현재 수열의 맨 왼쪽 숫자를 삭제하고 left 이동 +*/ +int main() { + int n, k; + vector numbers; + + //입력 + cin >> n >> k; + numbers.assign(n, 0); + for (int i = 0; i < n; i++) { + cin >> numbers[i]; + } + + //연산 & 출력 + cout << getMaxLen(numbers, n, k); + return 0; +======= #include #include #include @@ -38,4 +85,5 @@ int main() { cout << max_length; return 0; +} } \ No newline at end of file diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\355\225\204\354\210\230/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" deleted file mode 100644 index e69de29b..00000000 diff --git "a/12_\355\212\270\353\246\254/README.md" "b/12_\355\212\270\353\246\254/README.md" index e69de29b..a49a16e2 100644 --- "a/12_\355\212\270\353\246\254/README.md" +++ "b/12_\355\212\270\353\246\254/README.md" @@ -0,0 +1,75 @@ +# 트리 (Tree) + +[메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4) + +## 💻 튜터링 + +### 라이브 코딩 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :----------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :----------: | :--------: | +| 1991 | 트리 순회 | | [바로가기]() | 트리 순회 | +| 4803 | 트리 | | [바로가기]() | 트리, DFS | + +## ✏️ 과제 + +### 마감기한 + +~ 5 / 23 (화) 18:59 - 과제 제출
+~ 5 / 25 (목) 23:59 - 추가 제출
+ +### 필수 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :------------------------: | +| 3190 | | | [C++]() | 구현, 시뮬레이션, 자료구조 | +| 15681 | 트리와 쿼리 | | [C++]() | 트리, 그래프 탐색, DP | +| 5639 | 이진 검색 트리 | | [C++]() | 트리, 그래프 탐색 | + +### 도전 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :--------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :--: | +| 1967 | 트리의 지름 | | [C++]() | 트리, 그래프 탐색 | +| 24545 | Y | | [C++]() | 트리 그래프 탐색, DP | +--- + +### 힌트 + +
+ +
+    뱀의 머리와 꼬리에 변화가 생기고 있네요! 어떤 자료구조가 필요할까요? 뱀의 현재 위치를 직접 나타내보는 것도 좋을 것 같네요. +
+
+ +
+트리와 쿼리 +
+    모든 정점을 각각 루트로 하는 서브트리에서의 정점의 수를 빠르게 구해 둘 방법이 무엇일까요? 앞서 배운 알고리즘을 떠올려보세요! +
+
+ +
+이진 검색 트리 +
+    전위 순회한 결과를 루트와 왼쪽 오른쪽으로 나눠보고 후위 순회의 순서를 떠올려보세요! +
+
+ +
+트리의 지름 +
+    지름을 이루는 노드의 특징은 무엇일까요? +
+
+ +
+Y +
+    사용할 수 있는 정점의 종류를 고려해서 트리의 모양을 추측해보세요! 또 N이 생각보다 큰 것 같아요! +
+
+ + +--- diff --git "a/12_\355\212\270\353\246\254/\352\260\225\354\235\230 \354\236\220\353\243\214/12_\355\212\270\353\246\254_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" "b/12_\355\212\270\353\246\254/\352\260\225\354\235\230 \354\236\220\353\243\214/12_\355\212\270\353\246\254_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" new file mode 100644 index 00000000..2bb1c381 Binary files /dev/null and "b/12_\355\212\270\353\246\254/\352\260\225\354\235\230 \354\236\220\353\243\214/12_\355\212\270\353\246\254_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" differ diff --git "a/12_\355\212\270\353\246\254/\352\260\225\354\235\230 \354\236\220\353\243\214/12_\355\212\270\353\246\254_\354\235\264\353\241\240.pdf" "b/12_\355\212\270\353\246\254/\352\260\225\354\235\230 \354\236\220\353\243\214/12_\355\212\270\353\246\254_\354\235\264\353\241\240.pdf" new file mode 100644 index 00000000..e7c5dd8e Binary files /dev/null and "b/12_\355\212\270\353\246\254/\352\260\225\354\235\230 \354\236\220\353\243\214/12_\355\212\270\353\246\254_\354\235\264\353\241\240.pdf" differ diff --git "a/12_\355\212\270\353\246\254/\352\260\225\354\235\230 \354\236\220\353\243\214/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" "b/12_\355\212\270\353\246\254/\352\260\225\354\235\230 \354\236\220\353\243\214/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" deleted file mode 100644 index e69de29b..00000000 diff --git "a/12_\355\212\270\353\246\254/\355\225\204\354\210\230/15681_\354\266\224\352\260\200\354\240\234\354\266\234.cpp" "b/12_\355\212\270\353\246\254/\355\225\204\354\210\230/15681_\354\266\224\352\260\200\354\240\234\354\266\234.cpp" new file mode 100644 index 00000000..980e8564 --- /dev/null +++ "b/12_\355\212\270\353\246\254/\355\225\204\354\210\230/15681_\354\266\224\352\260\200\354\240\234\354\266\234.cpp" @@ -0,0 +1,57 @@ +#include +#include +#include + +using namespace std; + +/* + * 트리의 정점의 수 구하기 응용 문제 + * + * 1. 루트에서 DFS를 사용하여 탐색 + * 2. 각 노드를 루트로 하는 서브트리의 정점 수를 재귀적으로 벡터에 저장 + * - 서브트리에 속한 정점의 개수를 저장하는 dp 배열을 1로 초기화 + * - 탐색 시 현재 정점의 자식 노드만 탐색해서 현재 정점의 dp 값에 더해줌 + * 3. 쿼리로 주어지는 정점의 서브트리의 정점의 개수를 dp에서 찾아서 출력 + */ + +void dfs(int cur, int prev, vector>& tree, vector& dp) { + + for (int i = 0; i < tree[cur].size(); i++) { // 현재 정점의 자식 노드 탐색 + if (tree[cur][i] == prev) { + continue; + } + dfs(tree[cur][i], cur, tree, dp);//각 노드를 루트로 하는 서브트리 정점 수를 구하기 위해 재귀적 호출 + dp[cur] += dp[tree[cur][i]]; // 자식 노드의 dp값 더해주기 + } + + return; +} + +int main() { + + ios::sync_with_stdio(false); + cin.tie(0); + cout.tie(0); + + // 입력 + int n, r, q, u, v; + cin >> n >> r >> q; //n: 정점수, r:루트 번호, q:쿼리 수 + + vector>tree(n + 1, vector(0)); + + for (int i = 0; i < n - 1; i++) { + cin >> u >> v; + tree[u].push_back(v);//방향성이 없으므로 양쪽에 다 넣어줌 + tree[v].push_back(u); + } + + // 연산 + vectordp(n + 1, 1); // 자신도 자신을 루트로 하는 서브트리에 포함되므로 0이 아닌 1로 dp 초기값 설정 + dfs(r, 0, tree, dp); + + // 출력 + while (q--) { + cin >> u; + cout << dp[u] << '\n';//u를 루트노드로 삼는 서브트루의 정점 수 출력 + } +} \ No newline at end of file diff --git "a/12_\355\212\270\353\246\254/\355\225\204\354\210\230/3190_\354\266\224\352\260\200\354\240\234\354\266\234.cpp" "b/12_\355\212\270\353\246\254/\355\225\204\354\210\230/3190_\354\266\224\352\260\200\354\240\234\354\266\234.cpp" new file mode 100644 index 00000000..eaeea976 --- /dev/null +++ "b/12_\355\212\270\353\246\254/\355\225\204\354\210\230/3190_\354\266\224\352\260\200\354\240\234\354\266\234.cpp" @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +using namespace std; +typedef pair ci; + +/**뱀 게임이 종료되는 시간 계산*/ +int game(int n, vector>& state, map& direction) { + int dx[4] = { 0, 1, 0, -1 }; // 동(→), 남(↓), 서(←), 북(↑) + int dy[4] = { 1, 0, -1, 0 }; + int time = 0; // 게임 시간 + int dir = 0; // 뱀의 방향 + int x, y, nx, ny; + + deque snake; // 뱀의 위치 + snake.push_back({ 1, 1 }); // 뱀의 시작 좌표 추가 + state[1][1] = 2; // (1, 1)에 뱀이 있음을 표시 + + while (true) {//뱀의 머리가 벽에 부딪치거나 몸과 부딪치는 경우를 break로 설정하고 무한 반복 + x = snake.front().first; // 뱀의 머리 좌표 + y = snake.front().second; + if (direction[time] != 0) { // 뱀의 방향 변환 정보가 있으면 + dir = (dir + direction[time]) % 4; // 뱀의 방향 갱신 + } + time++; // 게임 시간 1초 추가 + nx = x + dx[dir]; // 뱀 머리의 다음 좌표 + ny = y + dy[dir]; + + // 뱀의 머리가 벽에 부딪히거나 자기 자신의 몸과 부딪히면 게임 종료 + if (!(0 < nx && nx <= n) || !(0 < ny && ny <= n) || state[nx][ny] == 2) { + break; //앞의 두조건은 벽에 부딪쳤을 때, 맨 뒤의 조건은 특정 칸=2->뱀은 한마리이므로 자기자신의 몸이 중복됨을 의미 + } + + snake.push_front({ nx, ny }); // 뱀의 머리 좌표 추가 + if (state[nx][ny] != 1) { // 새로 이동한 좌표에 사과가 없으면 꼬리 위치 비워주기 + state[snake.back().first][snake.back().second] = 0;//사과도 뱀도 없음 + snake.pop_back();//뱀의 좌표에서 빼줌 + } + state[nx][ny] = 2;//새로 이동한 좌표 표시 + } + return time;//시간 반환 +} +/**[백준 3190: 뱀] + * 뱀의 머리와 꼬리 좌표에 대한 접근 필요 -> deque 사용! + * state에 사과가 존재하면 해당 위치를 1, 뱀이 존재하면 2, 아무것도 없으면 0으로 설정 + * 1. 뱀의 첫 시작 좌표인 {1, 1}을 s에 추가 + * 2. 현재 뱀의 머리가 있는 좌표를 {x, y}로 받기 + * 3. 뱀의 방향이 바뀌면 방향을 업데이트하고, 새로운 뱀의 머리 좌표를 {nx, ny}로 설정 + * 4. 게임 시간 업데이트(time++) + * 4. 뱀의 머리가 벽이나 몸에 부딪히면 while문 종료 + * 5-1. 새로 이동한 좌표를 s 앞부분에 추가 + * 5-2. 새로 이동한 좌표에 사과가 없으면 기존 꼬리 좌표 값을 0으로 바꾸고 s에서 pop + * -> 사과가 있으면 몸길이가 1 늘어나지만 사과가 없으면 몸길이가 변하지 않으므로 + * 6. 새로 이동한 좌표를 2로 표시 +*/ +int main() { + int n, k, l, x; + char c; + vector> state;//좌표 + map direction;//뱀이 움직은 방향 + + // 입력 + cin >> n >> k; + state.assign(n + 1, vector(n + 1, 0)); + while (k--) {//사과:k개 + int a, b; + cin >> a >> b; + state[a][b] = 1; //사과 위치 표시 + } + + cin >> l;//방향변환 횟수 + while (l--) { + cin >> x >> c; + if (c == 'D') { + direction[x] = 1; // 오른쪽으로 회전 + } + else { + direction[x] = 3; // 왼쪽으로 회전 + } + } + + // 연산 + int time = game(n, state, direction); + + // 출력 + cout << time; + return 0; +} \ No newline at end of file diff --git "a/12_\355\212\270\353\246\254/\355\225\204\354\210\230/5639.cpp" "b/12_\355\212\270\353\246\254/\355\225\204\354\210\230/5639.cpp" new file mode 100644 index 00000000..71942765 --- /dev/null +++ "b/12_\355\212\270\353\246\254/\355\225\204\354\210\230/5639.cpp" @@ -0,0 +1,59 @@ +#include +#include +using namespace std; + +struct node { + int data; + node* left; + node* right; +}; + +node* insert(node* tree, int num) { + if (tree == NULL) {//루트 노드 + tree = new node(); + tree->data = num;//데이터 삽임 + tree->right = NULL; + tree->left = NULL; + } + + else if (num < tree->data) {//부모 보다 작으면 왼쪽에 삽입 + tree->left = insert(tree->left, num);//재귀적으로 호출 + } + else {//같은 경우는 존재x, 부모보다 크면 오르쪽에 삽입 + tree->right = insert(tree->right, num); + + } + return tree; +} + +void postorder(node* tree) { + //postorder는 left->right->root 순서이므로 left자식이 있는지 체크하는 if문이 먼저옴 + if (tree->left !=NULL) {//왼쪽 자식이 존재한다면 + postorder(tree->left);//왼쪽 자식 호출 + } + if (tree->right != NULL) {//오른쪽 자식이 존재한다면 호출 + postorder(tree->right); + } + cout << tree->data << "\n";//더이상 자식이 없다면 출력, 이후 다시 부모 노드로 돌아옴 +} + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(NULL); + cout.tie(NULL); + + int num = 0; + node* tree = NULL; + //입력 및 트리 생성 + while (cin >> num) { + if (num == EOF) { + break; + } + tree=insert(tree, num); + } + + //출력 + postorder(tree); + + return 0; +} \ No newline at end of file diff --git a/README.md b/README.md index dbf4b4d4..45c0fca2 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ SW학부 원스탑 튜터링에서 진행하는 코딩 테스트 대비 알고 | 2023.04.14 | 동적 계획법 | [@sujeong000](https://github.com/sujeong000) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/09_%EB%8F%99%EC%A0%81%20%EA%B3%84%ED%9A%8D%EB%B2%95/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C/09_%EB%8F%99%EC%A0%81%EA%B3%84%ED%9A%8D%EB%B2%95_%EC%9D%B4%EB%A1%A0.pdf) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/09_%EB%8F%99%EC%A0%81%20%EA%B3%84%ED%9A%8D%EB%B2%95) | - | | 2023.05.05 | 이분 탐색 | [@grdnr13](https://github.com/grdnr13) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/10_%EC%9D%B4%EB%B6%84%20%ED%83%90%EC%83%89/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C/10_%EC%9D%B4%EB%B6%84%ED%83%90%EC%83%89_%EC%9D%B4%EB%A1%A0.pdf) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/10_%EC%9D%B4%EB%B6%84%20%ED%83%90%EC%83%89) | 녹화 강의 제공 | | 2023.05.12 | 투 포인터 | [@kwakrhkr59](https://github.com/kwakrhkr59) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/11_%ED%88%AC%20%ED%8F%AC%EC%9D%B8%ED%84%B0/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/11_%ED%88%AC%20%ED%8F%AC%EC%9D%B8%ED%84%B0) | - | -| 2023.05.19 | 트리 | [@dbswn](https://github.com/dbswn) | [바로가기]() | [바로가기]() | - | +| 2023.05.19 | 트리 | [@dbswn](https://github.com/dbswn) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/12_%ED%8A%B8%EB%A6%AC/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C/12_%ED%8A%B8%EB%A6%AC_%EC%9D%B4%EB%A1%A0.pdf) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/12_%ED%8A%B8%EB%A6%AC) | - | | 2023.05.26 | 최단 경로 | [@Dong-droid](https://github.com/Dong-droid) | [바로가기]() | [바로가기]() | - | | 2023.06.02 | 유니온 파인드 | [@bsa0322](https://github.com/bsa0322) | [바로가기]() | [바로가기]() | 2기 자료 제공 | | 2023.06.02 | 최소 신장 트리 | [@ZERO-black](https://github.com/ZERO-black) | [바로가기]() | [바로가기]() | 2기 자료 제공 |