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

[12 트리] 1914039 최유진 #339

Open
wants to merge 10 commits into
base: 1914039-최유진
Choose a base branch
from
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;
}
60 changes: 60 additions & 0 deletions 11_투 포인터/필수/20437.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,62 @@

#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";
=======
#include<iostream>
#include<vector>
#include<string>
Expand Down Expand Up @@ -52,6 +111,7 @@ int main() {
}
else {
cout << min_length << " " << max_length << "\n"; //문자열을 찾은 경우->출력

}
}
return 0;
Expand Down
Loading