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

[13 최단경로] 1914039 최유진 #358

Open
wants to merge 25 commits into
base: 1914039-최유진
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
077bd1b
[5월 16일] 투 포인터 과제 코드 업로드
jk0527 May 16, 2023
b48257f
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 16, 2023
198416c
[5월 16일] 투 포인터 리드미 수정
jk0527 May 16, 2023
5536b51
[5월 16일] 트리 강의 자료 업로드
jk0527 May 16, 2023
9bf8964
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 16, 2023
cd29d82
[5월 16일] 트리 리드미 업로드
jk0527 May 16, 2023
f5fd534
[5월 16일] 리드미 수정
jk0527 May 16, 2023
5c5694a
[5월 19일] 트리 라이브 코딩 코드 업로드
jk0527 May 19, 2023
cf31227
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 19, 2023
a8cc122
[5월 19일] 트리 리드미 수정
jk0527 May 19, 2023
5ab3590
[5월 23일] 트리 과제 코드 업로드
jk0527 May 23, 2023
20be664
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 23, 2023
dad8d2c
[5월 23일] 트리 리드미 수정
jk0527 May 23, 2023
1373cde
[5월 23일] 최단 경로 강의 자료 업로드
jk0527 May 23, 2023
6d1de48
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 23, 2023
b57dc56
[5월 23일] 최단 경로 리드미 업로드
jk0527 May 23, 2023
c908c33
[5월 23일] 리드미 수정
jk0527 May 23, 2023
dfb69e0
[5월 26일] 최단 경로 강의 자료 수정
jk0527 May 26, 2023
65bd5df
[5월 26일] 최단 경로 강의 자료 수정
jk0527 May 26, 2023
7b46298
[5월 26일] 최단 경로 라이브 코딩 코드 업로드
jk0527 May 26, 2023
74a7044
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 26, 2023
fce223d
[5월 26일] 최단 경로 리드미 수정
jk0527 May 26, 2023
75b3e95
[13 최단경로]0530
choi-yujin May 30, 2023
cec1b95
[13 최단경로] 0601-추가제출
choi-yujin Jun 1, 2023
c588453
Merge branch '1914039-최유진' into 1914039-13
choi-yujin Jun 1, 2023
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
10 changes: 5 additions & 5 deletions 11_투 포인터/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@

| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 |
| :-----------------------------------------------------------------------: | :------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :------------------------: |
| <a href="https://www.acmicpc.net/problem/14503" target="_blank">14503</a> | <a href="https://www.acmicpc.net/problem/14503" target="_blank">로봇 청소기</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/11.svg"/> | [C++]() | 구현, 시뮬레이션 |
| <a href="https://www.acmicpc.net/problem/20922" target="_blank">20922</a> | <a href="https://www.acmicpc.net/problem/20922" target="_blank">겹치는 건 싫어</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/10.svg"/> | [C++]() | 투 포인터 |
| <a href="https://www.acmicpc.net/problem/20437" target="_blank">20437</a> | <a href="https://www.acmicpc.net/problem/20437" target="_blank">문자열 게임 2</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/11.svg"/> | [C++]() | 슬라이딩 윈도우 |
| <a href="https://www.acmicpc.net/problem/14503" target="_blank">14503</a> | <a href="https://www.acmicpc.net/problem/14503" target="_blank">로봇 청소기</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/11.svg"/> | [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) </br> [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) | 구현, 시뮬레이션 |
| <a href="https://www.acmicpc.net/problem/20922" target="_blank">20922</a> | <a href="https://www.acmicpc.net/problem/20922" target="_blank">겹치는 건 싫어</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/10.svg"/> | [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) | 투 포인터 |
| <a href="https://www.acmicpc.net/problem/20437" target="_blank">20437</a> | <a href="https://www.acmicpc.net/problem/20437" target="_blank">문자열 게임 2</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/11.svg"/> | [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) | 슬라이딩 윈도우 |

### 도전

| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 |
| :--------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :--: |
| <a href="https://www.acmicpc.net/problem/13422" target="_blank">13422</a> | <a href="https://www.acmicpc.net/problem/13422" target="_blank">도둑</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/12.svg"/> | [C++]() | 투 포인터, 슬라이딩 윈도우 |
| <a href="https://www.acmicpc.net/problem/2473" target="_blank">2473</a> | <a href="https://www.acmicpc.net/problem/2473" target="_blank">세 용액</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/13.svg"/> | [C++]() | 투 포인터 |
| <a href="https://www.acmicpc.net/problem/13422" target="_blank">13422</a> | <a href="https://www.acmicpc.net/problem/13422" target="_blank">도둑</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/12.svg"/> | [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) | 투 포인터, 슬라이딩 윈도우 |
| <a href="https://www.acmicpc.net/problem/2473" target="_blank">2473</a> | <a href="https://www.acmicpc.net/problem/2473" target="_blank">세 용액</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/13.svg"/> | [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) | 투 포인터 |
---

### 힌트
Expand Down
51 changes: 51 additions & 0 deletions 11_투 포인터/도전/13422.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <iostream>
#include <vector>
using namespace std;

/**m개의 집에서 k보다 작은 돈을 훔칠 수 있는 경우의 수 구하기*/
int steal(vector<int> 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<int> 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;
}
64 changes: 64 additions & 0 deletions 11_투 포인터/도전/2473.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <iostream>
#include <vector>
#include <tuple>
#include <cmath> // abs()
#include <algorithm> // sort()

#define INF 3 * 1e9 + 1
typedef long long ll;
using namespace std;

/**투 포인로 세 용액의 합이 가장 0에 가까운 용액 튜플 리턴*/
tuple<int, int, int> calSum(vector<ll> liquid) {
ll min_value = INF;
tuple<int, int, int> 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<ll> liquid;

// 입력
cin >> n;
liquid.assign(n, 0);
for (int i = 0; i < n; i++) {
cin >> liquid[i];
}

// 연산
sort(liquid.begin(), liquid.end());
tuple<int, int, int> ans = calSum(liquid);

// 출력
cout << get<0>(ans) << " " << get<1>(ans) << " " << get<2>(ans);
return 0;
}
Empty file.
74 changes: 74 additions & 0 deletions 11_투 포인터/필수/14503_v1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <iostream>

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;
}
79 changes: 79 additions & 0 deletions 11_투 포인터/필수/14503_v2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <iostream>
#include <vector>

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<vector<int>> &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<vector<int>> board;

// 입력
cin >> n >> m;
cin >> r >> c >> d;
board.assign(n, vector<int> (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;
}
61 changes: 61 additions & 0 deletions 11_투 포인터/필수/20437.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
typedef pair<int, int> ci;
const int MAX_ALPHA = 26; // 알파벳 개수

/**문자를 k개 포함하는 가장 짧은 문자열과 가장 긴 문자열의 쌍 구하기*/
ci solution(string w, int k) {
vector<vector<int>> 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";
}
}
return 0;
}
Loading