diff --git "a/01_\354\240\225\353\240\254, \353\247\265, \354\205\213/\352\260\225\354\235\230 \354\236\220\353\243\214/01_\354\240\225\353\240\254,_\353\247\265,_\354\205\213_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" "b/01_\354\240\225\353\240\254, \353\247\265, \354\205\213/\352\260\225\354\235\230 \354\236\220\353\243\214/01_\354\240\225\353\240\254,_\353\247\265,_\354\205\213_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" index 8cfe499f..3d3ad536 100644 Binary files "a/01_\354\240\225\353\240\254, \353\247\265, \354\205\213/\352\260\225\354\235\230 \354\236\220\353\243\214/01_\354\240\225\353\240\254,_\353\247\265,_\354\205\213_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" and "b/01_\354\240\225\353\240\254, \353\247\265, \354\205\213/\352\260\225\354\235\230 \354\236\220\353\243\214/01_\354\240\225\353\240\254,_\353\247\265,_\354\205\213_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" differ diff --git "a/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/README.md" "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/README.md" index 499c8345..41274b93 100644 --- "a/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/README.md" +++ "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/README.md" @@ -1,4 +1,4 @@ -# 스택, 큐, 덱 (Stack Queue, Deque) +# 스택, 큐, 덱 (Stack, Queue, Deque) [메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4) @@ -6,8 +6,8 @@ ### 라이브 코딩 -| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | -| :-----------------------------------------------------------------------: | :----------------------------------------------------------------------: | :-------------------------------------------------------------------------------: | :----------: | :--: | +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :----------------------------------------------------------------------: | :-------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--: | | 10828 | 스택 | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/02_%EC%8A%A4%ED%83%9D%2C%20%ED%81%90%2C%20%EB%8D%B1/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/10828.cpp) | 스택 | | 10845 | | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/02_%EC%8A%A4%ED%83%9D%2C%20%ED%81%90%2C%20%EB%8D%B1/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/10845.cpp) | 큐 | | 10866 | | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/02_%EC%8A%A4%ED%83%9D%2C%20%ED%81%90%2C%20%EB%8D%B1/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/10866.cpp) | 덱 | @@ -21,18 +21,18 @@ ### 필수 -| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | -| :-----------------------------------------------------------------------: | :------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------: | :-------: | :--: | -| 10757 | 큰 수 A+B | | [C++]() | 구현 | -| 1158 | 요세푸스 문제 | | [C++]() | 큐 | -| 4949 | 균형잡힌 세상 | | [C++]() | 스택 | +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--: | +| 10757 | 큰 수 A+B | | [C++[1]](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/02_%EC%8A%A4%ED%83%9D%2C%20%ED%81%90%2C%20%EB%8D%B1/%ED%95%84%EC%88%98/10757_v1.cpp) [C++[2]](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/02_%EC%8A%A4%ED%83%9D%2C%20%ED%81%90%2C%20%EB%8D%B1/%ED%95%84%EC%88%98/10757_v2.cpp) | 구현 | +| 1158 | 요세푸스 문제 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/02_%EC%8A%A4%ED%83%9D%2C%20%ED%81%90%2C%20%EB%8D%B1/%ED%95%84%EC%88%98/1158.cpp) | 큐 | +| 4949 | 균형잡힌 세상 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/02_%EC%8A%A4%ED%83%9D%2C%20%ED%81%90%2C%20%EB%8D%B1/%ED%95%84%EC%88%98/4949.cpp) | 스택 | ### 도전 -| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | -| :--------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :--: | -| 프로그래머스 | 기능개발 | **Lv.2** | [C++]() | 큐 | -| 1918 | 후위 표기식 | | [C++]() | 스택 | +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :--------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--: | +| 프로그래머스 | 기능개발 | **Lv.2** | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/02_%EC%8A%A4%ED%83%9D%2C%20%ED%81%90%2C%20%EB%8D%B1/%EB%8F%84%EC%A0%84/%EA%B8%B0%EB%8A%A5%EA%B0%9C%EB%B0%9C.cpp) | 큐 | +| 1918 | 후위 표기식 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/02_%EC%8A%A4%ED%83%9D%2C%20%ED%81%90%2C%20%EB%8D%B1/%EB%8F%84%EC%A0%84/1918.cpp) | 스택 | --- diff --git "a/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\353\217\204\354\240\204/1918.cpp" "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\353\217\204\354\240\204/1918.cpp" new file mode 100644 index 00000000..7707dee1 --- /dev/null +++ "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\353\217\204\354\240\204/1918.cpp" @@ -0,0 +1,78 @@ +#include +#include + +using namespace std; + +int priority(char ch) { // 연산자 우선순위 반환 + switch(ch) { + case '(': return 0; + case '+': case '-': return 1; + case '*': case '/': return 2; // 연산자 순위 가장 높음 (먼저 계산되어야 함) + } +} + +string postfix(string input) { // 중위 표기식 -> 후위 표기식 + string result = ""; // 후위 표기식 + stack op; // 연산자 저장하는 스택 + + for(int i = 0; i < input.size(); i++) { + char ch = input[i]; + switch(ch) { + // 여는 괄호는 무조건 push + case '(': + op.push(ch); + break; + + // 닫는 괄호는 여는 괄호를 만날 때까지 pop + case ')': + while(!op.empty() && op.top() != '(') { + result += op.top(); + op.pop(); + } + op.pop(); // 여는 괄호 제거 + break; + + // 연산자의 경우, 스택에 들어있는 연산자와 우선순위 비교 + case '+': case '-': case '*': case '/': + // 스택에 현재 연산자보다 우선순위가 높은 (=먼저 계산되어야 하는) 연산자가 있는 경우 pop + while(!op.empty() && priority(op.top()) >= priority(ch)) { + result += op.top(); + op.pop(); + } + op.push(ch); // 현재 연산자 push + break; + + // 피연산자는 바로 결과에 추가 + default: + result += ch; + } + } + + // 스택에 남아있는 연산자 결과에 추가 + while(!op.empty()) { + result += op.top(); + op.pop(); + } + return result; +} + +/* + * [중위 표기식 -> 후위 표기식] + * 1. 피연산자는 순서가 변하지 않으므로 바로 결과에 추가한다. + * 2. 연산자는 우선순위에 따라 순서가 변하므로 스택에 잠시 저장한다. + * 3. 스택의 top에 있는 연산자는 우선순위가 제일 높아야 한다. + * 4. 스택의 top에 있는 연산자가 현재 연산자보다 우선순위가 같거나 높으면 스택에서 값을 꺼내야 한다. + * 5. 여는 괄호는 무조건 스택에 넣는다. + * 6. 닫는 괄호가 들어오면 여는 괄호가 나올 때까지 스택에 있는 연산자를 결과에 추가한다. +*/ + +int main() { + string input; // 입력값 (중위 표기식) + + // 입력 + cin >> input; + + // 연산 & 출력 + cout << postfix(input); + return 0; +} \ No newline at end of file diff --git "a/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\353\217\204\354\240\204/\352\270\260\353\212\245\352\260\234\353\260\234.cpp" "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\353\217\204\354\240\204/\352\270\260\353\212\245\352\260\234\353\260\234.cpp" new file mode 100644 index 00000000..e246627c --- /dev/null +++ "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\353\217\204\354\240\204/\352\270\260\353\212\245\352\260\234\353\260\234.cpp" @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include + +using namespace std; + +queue completionTime(int n, vector progresses, vector speeds) { // 작업별 완료시간 반환 + queue q; // 작업 완료시간 + + for(int i = 0; i < n; i++) { + int remain = 100 - progresses[i]; // 남은 작업량 + q.push(ceil((double) remain / speeds[i])); // 완료시간 계산 + } + return q; +} + +vector solution(vector progresses, vector speeds) { + vector answer; + + int n = progresses.size(); // 작업 개수 + queue q = completionTime(n, progresses, speeds); // 작업 완료시간 + + while(!q.empty()) { + int curr_time = q.front(); // 현재 작업의 완료 시간 + q.pop(); + int cnt = 1; // 현재 작업과 함께 배포될 수 있는 작업 수 + + // 현재 작업과 함께 배포할 수 있는 작업 세기 + // q.front() : 현재 작업보다 뒷순서인 작업의 완료 시간 + while(!q.empty() && q.front() <= curr_time) { + q.pop(); + cnt++; + } + answer.push_back(cnt); + } + return answer; +} + +/* + * 배포 프로세스 : 작업 완료 후 배포 + * 1. 작업별 작업 완료 시간을 계산한다. + * 2. 작업 순서대로 배포를 시작한다. + * + * HINT : 뒷 순서의 작업이 앞 순서보다 먼저 개발될 수는 있지만 '먼저 배포될 수는 없다' + * -> 앞 순서의 작업이 먼저 배포되는 (== FIFO) 구조 +*/ + +int main() { + vector progresses = {93, 30, 55}; + vector speeds = {1, 30, 5}; + + // 연산 + vector answer = solution(progresses, speeds); + + // 출력 + for(int i = 0; i < answer.size(); i++) { + cout << answer[i] << ' '; + } + return 0; +} \ No newline at end of file diff --git "a/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\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/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\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/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/10757_v1.cpp" "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/10757_v1.cpp" new file mode 100644 index 00000000..e511862f --- /dev/null +++ "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/10757_v1.cpp" @@ -0,0 +1,67 @@ +// 벡터 사용 +#include +#include +using namespace std; + +/* + 매개변수에 &를 붙이면 원본을 참조하게 됩니다. + **이 문제에서는 굳이 참조자를 사용할 필요는 없지만, C++에서는 주로 &를 붙입니다** +*/ +int charToint(char ch){ + return (ch - '0'); +} + +vector calcPlus(string &a, string &b) { + int idx_a = a.size() - 1; // 일의 자리 인덱스 + int idx_b = b.size() - 1; + bool carry = false; + vector ans; + + while (idx_a >= 0 && idx_b >= 0) { + int num = charToint(a[idx_a--]) + charToint(b[idx_b--]); // 문자를 숫자로 바꾸어 더하기, 그리고 인덱스 변경 + + num += carry; // num에 carry 더해주기. (carry는 어차피 1 아니면 0) + carry = num / 10; // num의 값이 10이상이면 carry가 1, 아니면 0 + ans.push_back(num % 10); // 올림을 제외한 값만 스택에 push + } + + // a에서 남은 숫자 반영 + while (idx_a >= 0) { + int num = charToint(a[idx_a--]); + + num += carry; + carry = num / 10; + ans.push_back(num % 10); + } + + // 남은 올림 확인 + if (carry){ + ans.push_back(1); + } + + return ans; +} + +int main() { + ios::sync_with_stdio(0); + cin.tie(0); + + string a, b; + vector ans; + + //입력 + cin >> a >> b; + + //연산 + if (a.length() < b.length()) { // b의 길이가 더 길다면 + swap(a, b); + } + + ans = calcPlus(a, b); + + //출력 + while (!ans.empty()) { + cout << ans.back(); + ans.pop_back(); + } +} diff --git "a/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/10757_v2.cpp" "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/10757_v2.cpp" new file mode 100644 index 00000000..4bd0b58b --- /dev/null +++ "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/10757_v2.cpp" @@ -0,0 +1,61 @@ +// 스택 사용 +#include +#include +using namespace std; + +/* + 매개변수에 &를 붙이면 원본을 참조하게 됩니다. + **이 문제에서는 굳이 참조자를 사용할 필요는 없지만, C++에서는 주로 &를 붙입니다** +*/ +stack calcPlus(string &a, string &b) { + int idx_a = a.size() - 1; // 일의 자리 인덱스 + int idx_b = b.size() - 1; + bool carry = false; + stack ans; + + while (idx_a >= 0 && idx_b >= 0) { + int num = (a[idx_a--] - '0') + (b[idx_b--] - '0'); // 문자를 숫자로 바꾸어 더하기, 그리고 인덱스 변경 + + num += carry; // num에 carry 더해주기. (carry는 어차피 1 아니면 0) + carry = num / 10; // num의 값이 10이상이면 carry가 1, 아니면 0 + ans.push(num % 10); // 올림을 제외한 값만 스택에 push + } + + // a에서 남은 숫자 반영 + while (idx_a >= 0) { + int num = a[idx_a--] - '0'; + + num += carry; + carry = num / 10; + ans.push(num % 10); + } + + // 남은 올림 확인 + if (carry) + ans.push(1); + + return ans; +} + +int main() { + ios::sync_with_stdio(0); + cin.tie(0); + + string a, b; + stack ans; + + //입력 + cin >> a >> b; + + //연산 + if (a.length() < b.length()) // b의 길이가 더 길다면 + swap(a, b); + + ans = calcPlus(a, b); + + //출력 + while (!ans.empty()) { + cout << ans.top(); + ans.pop(); + } +} diff --git "a/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/1158.cpp" "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/1158.cpp" new file mode 100644 index 00000000..292a653e --- /dev/null +++ "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/1158.cpp" @@ -0,0 +1,50 @@ +#include +#include + +using namespace std; + +vector josephus(int n, int k) { // 요세푸스 순열 반환 + vector result; // 요세푸스 순열 + queue q; // 원 + + for(int i = 1; i <= n; i++) { // 원 초기화 + q.push(i); + } + + while(!q.empty()) { + for(int i = 0; i < k-1; i++) { // k-1번 pop & push + q.push(q.front()); + q.pop(); + } + + // k번째 사람 pop 후 순열에 추가 + result.push_back(q.front()); + q.pop(); + } + return result; +} + +/* + * 원을 따라 k번째 사람을 제거한다. + * 1. k번째 사람이 아닌 사람은 원의 맨 뒤로 보낸다. + * 2. k번째 사람은 원에서 제거한다. +*/ + +int main() { + int n, k; + queue q; + + // 입력 + cin >> n >> k; + + // 연산 + vector result = josephus(n, k); + + // 출력 + cout << "<" << result[0]; + for(int i = 1; i < n; i++) { + cout << ", " << result[i]; + } + cout << ">"; + return 0; +} \ No newline at end of file diff --git "a/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/4949.cpp" "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/4949.cpp" new file mode 100644 index 00000000..b4d63051 --- /dev/null +++ "b/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\355\225\204\354\210\230/4949.cpp" @@ -0,0 +1,61 @@ +#include +#include + +using namespace std; + +bool isBalanced(string input) { // 괄호가 균형을 이루었는지 여부 반환 + stack s; // 괄호 저장하는 스택 + + for(int i = 0; i < input.length(); i++) { + char ch = input[i]; + switch(ch) { + case '(': case '[': // 여는 괄호는 무조건 push + s.push(ch); + break; + case ')': // 닫는 소괄호 + if(s.empty() || s.top() != '(') { + return false; + } + s.pop(); + break; + case ']': // 닫는 대괄호 + if(s.empty() || s.top() != '[') { + return false; + } + s.pop(); + break; + } + } + return s.empty(); +} + +/* + * [괄호 균형 확인하기] + * 1. 여는 괄호는 바로 스택에 넣는다. + * 2. 닫는 괄호가 나오면 가장 최근에 넣었던 여는 괄호와 비교한다. + * 2-1. 닫는 괄호와 여는 괄호의 종류가 같다면 해당 닫는 괄호가 균형을 이룬다. + * 2-2. 직전에 나온 여는 괄호가 없거나 그 종류가 다르다면 해당 닫는 괄호가 균형을 이루지 못한다. + * 3. 모든 닫는 괄호가 여는 괄호와 짝을 이루었더라도 스택에 여는 괄호가 남아있다면 균형을 이루지 못한다. +*/ + + +int main() { + string input; + + while(true) { + // 입력 + getline(cin, input); + if(input == ".") { + break; + } + + // 연산 & 출력 + if(isBalanced(input)) { + cout << "yes\n"; + } + else { + cout << "no\n"; + } + } + return 0; +} \ No newline at end of file diff --git "a/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\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/02_\354\212\244\355\203\235, \355\201\220, \353\215\261/\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/03_\354\240\225\354\210\230\353\241\240/README.md" "b/03_\354\240\225\354\210\230\353\241\240/README.md" index e69de29b..e88e26f4 100644 --- "a/03_\354\240\225\354\210\230\353\241\240/README.md" +++ "b/03_\354\240\225\354\210\230\353\241\240/README.md" @@ -0,0 +1,77 @@ +# 정수론 (Number Theory) + +[메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4) + +## 💻 튜터링 + +### 라이브 코딩 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :----------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :----------: | :-----------------: | +| 2609 | 최대공약수와 최소공배수 | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/03_%EC%A0%95%EC%88%98%EB%A1%A0/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/2609.cpp) | 유클리드 호제법 | +| 2960 | 에라토스테네스의 체 | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/03_%EC%A0%95%EC%88%98%EB%A1%A0/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/2960.cpp) | 에라토스테네스의 체 | +| 16563 | 어려운 소인수분해 | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/03_%EC%A0%95%EC%88%98%EB%A1%A0/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/16563.cpp) | 에라토스테네스의 체 | + +## ✏️ 과제 + +### 마감기한 + +~ 3 / 7 (화) 18:59 - 과제 제출
+~ 3 / 9 (목) 23:59 - 추가 제출
+ +### 필수 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :---------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :-----------------: | +| 2840 | 행운의 바퀴 | | [C++_v1](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/03_%EC%A0%95%EC%88%98%EB%A1%A0/%ED%95%84%EC%88%98/2840_v1.cpp)
[C++_v2](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/03_%EC%A0%95%EC%88%98%EB%A1%A0/%ED%95%84%EC%88%98/2840_v2.cpp) | 구현, 시뮬레이션 | +| 6588 | 골드바흐의 추측 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/03_%EC%A0%95%EC%88%98%EB%A1%A0/%ED%95%84%EC%88%98/6588.cpp) | 에라토스테네스의 체 | +| 1735 | 분수 합 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/03_%EC%A0%95%EC%88%98%EB%A1%A0/%ED%95%84%EC%88%98/1735.cpp) | 유클리드 호제법 | + +### 도전 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :---------------------------------------------------------------------: | :---------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :----------------------------: | +| 9421 | 소수상근수 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/03_%EC%A0%95%EC%88%98%EB%A1%A0/%EB%8F%84%EC%A0%84/9421.cpp) | 에라토스테네스의 체, 소수 판정 | +| 2981 | 검문 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/03_%EC%A0%95%EC%88%98%EB%A1%A0/%EB%8F%84%EC%A0%84/2981.cpp) | 유클리드 호제법 | + +--- + +### 힌트 + +
+행운의 바퀴 +
+    바퀴를 배열로 고정시키고, 화살표를 움직인다면 화살표는 배열의 왼쪽 방향으로 이동하겠죠? 바퀴를 돌리는 횟수가 매우 클 수도 있으니 인덱스가 음수가 되지 않도록 유의해야 해요. +
+
+ +
+골드바흐의 추측 +
+    b - a가 가장 큰 경우가 언제일지 잘 생각해보아요! n = a + b를 만족시키는 두 소수들을 어디서부터 탐색하면 좋을까요? +
+
+ +
+분수 합 +
+    기약분수는 분모와 분자가 더 이상 약분되지 않는 분수를 말하죠! 어렵게 생각하지 말고 차근차근 두 분수를 더하고 약분해줍시다. +
+
+ +
+소수상근수 +
+    소수를 찾았다면 상근수인지 판단하면 되겠네요. 문제에서 주어진 그대로 구현해볼까요? 각 자릿수의 제곱의 합을 구할 때, 언제 그만둬야 할지 잘 생각해봐야겠어요. + +
+
+ +
+검문 +
+    입력으로 주어진 모든 수에 대하여 나눴을 때 나머지가 모두 같게 하는 M을 보다 효율적으로 판단해주려면 어떻게 해야 할까요? 접근이 어렵다면 각 수를 몫과 나머지로 나타내보면 좋을 것 같아요. +
+
+ +--- diff --git "a/03_\354\240\225\354\210\230\353\241\240/\352\260\225\354\235\230 \354\236\220\353\243\214/03_\354\240\225\354\210\230\353\241\240_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" "b/03_\354\240\225\354\210\230\353\241\240/\352\260\225\354\235\230 \354\236\220\353\243\214/03_\354\240\225\354\210\230\353\241\240_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" new file mode 100644 index 00000000..d2858f91 Binary files /dev/null and "b/03_\354\240\225\354\210\230\353\241\240/\352\260\225\354\235\230 \354\236\220\353\243\214/03_\354\240\225\354\210\230\353\241\240_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" differ diff --git "a/03_\354\240\225\354\210\230\353\241\240/\352\260\225\354\235\230 \354\236\220\353\243\214/03_\354\240\225\354\210\230\353\241\240_\354\235\264\353\241\240.pdf" "b/03_\354\240\225\354\210\230\353\241\240/\352\260\225\354\235\230 \354\236\220\353\243\214/03_\354\240\225\354\210\230\353\241\240_\354\235\264\353\241\240.pdf" new file mode 100644 index 00000000..aca45450 Binary files /dev/null and "b/03_\354\240\225\354\210\230\353\241\240/\352\260\225\354\235\230 \354\236\220\353\243\214/03_\354\240\225\354\210\230\353\241\240_\354\235\264\353\241\240.pdf" differ diff --git "a/03_\354\240\225\354\210\230\353\241\240/\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/03_\354\240\225\354\210\230\353\241\240/\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/03_\354\240\225\354\210\230\353\241\240/\353\217\204\354\240\204/2981.cpp" "b/03_\354\240\225\354\210\230\353\241\240/\353\217\204\354\240\204/2981.cpp" new file mode 100644 index 00000000..5d1912b8 --- /dev/null +++ "b/03_\354\240\225\354\210\230\353\241\240/\353\217\204\354\240\204/2981.cpp" @@ -0,0 +1,66 @@ +#include +#include +#include // sort() 이용 + +using namespace std; + +// 최대공약수(GCD) 계산 함수: 유클리드 호제법 이용 +int getGCD(int a, int b) { + if (b == 0) { + return a; + } + return getGCD(b, a % b); +} + +// 가능한 M 검색 함수 +vector solution(int n, vector &numbers) { + vector result; //가능한 M 저장 + + // 1. 검문소 사이 간격의 최대공약수(최대 M) 계산 + int gcd = numbers[1] - numbers[0]; + for (int i = 2; i < n; i++) { + gcd = getGCD(gcd, numbers[i] - numbers[i - 1]); + } + + // 2. 가능한 모든 M 찾기: 최대공약수의 약수 찾기 + for (int i = 2; i * 2 <= gcd; i++) { + if (gcd % i == 0) { + result.push_back(i); + } + } + result.push_back(gcd); + + return result; +} + +/* [백준 2981: 검문] + * A, B, C를 M으로 나눴을 때의 나머지가 모두 같을 때, 이 나머지 값을 K라 하면 + * A = M * a + K, B = M * b + K, C = M * c + K 이므로 + * B - A = (M * b + K) - (M * a + K) = M(b - a) + * C - B = (M * c + K) - (M * b + K) = M(c - b) + * 즉, 우리가 구해야 하는 M은 각 검문소 사이 간격 간의 모든 공약수! + * + * 1. 검문소 사이 간격 간의 최대공약수 구하기 + * 2. 1에서 구한 최대공약수의 모든 약수 구하기 + * (모든 약수를 구할 때 시간초과 주의!) + */ + +int main() { + // 입력 + int n; + cin >> n; + vector numbers(n); + for (int i = 0; i < n; i++) { + cin >> numbers[i]; + } + + // 연산 + sort(numbers.begin(), numbers.end()); + vector result = solution(n, numbers); + + // 출력 + for (int i : result) { + cout << i << " "; + } + return 0; +} \ No newline at end of file diff --git "a/03_\354\240\225\354\210\230\353\241\240/\353\217\204\354\240\204/9421.cpp" "b/03_\354\240\225\354\210\230\353\241\240/\353\217\204\354\240\204/9421.cpp" new file mode 100644 index 00000000..68e78e52 --- /dev/null +++ "b/03_\354\240\225\354\210\230\353\241\240/\353\217\204\354\240\204/9421.cpp" @@ -0,0 +1,81 @@ +#include +#include +#include + +using namespace std; + +// 각 자리수의 제곱의 합 계산 함수 +int getSum(int n) { + int total = 0, tmp; + while (n != 0) { + tmp = n % 10; + n /= 10; + total += tmp * tmp; + } + return total; +} +// 소수 여부 반환 함수: 에라토스테네스의 체 이용 +vector getPrimes(int n) { + vector is_prime(n+1, true); + is_prime[0] = is_prime[1] = false; + for (int i = 2; i * i <= n; i++) { + if (!is_prime[i]) { + continue; + } + for (int j = i * i; j <= n; j += i) { + is_prime[j] = false; + } + } + return is_prime; +} +// 소수상근수 여부 반환 함수 +bool is_valid(int n) { + set visited; + visited.insert(n); + while(1) { + n = getSum(n); + if (n == 1) { + return true; + } + if (visited.find(n) != visited.end()) { + return false; + } + visited.insert(n); + } +} + +// n보다 작거나 같은 소수상근수 벡터 반환 +vector solution(int n) { + vector is_prime = getPrimes(n); + vector result; + for (int i = 2; i <= n; i++) { + if (is_prime[i] && is_valid(i)) { + result.push_back(i); + } + } + return result; +} + +/* [백준 9421: 소수상근수] + * 상근수는 각 자리수의 제곱의 합을 재귀적으로 계산했을 때 1이 되는 수이다. + * 즉, 각 자리수의 제곱의 합을 재귀적으로 계산했을 때 + * 이전에 나왔던 값이 다시 나온다면 그 수는 상근수가 될 수 없다. + * 1. n보다 작거나 같은 모든 소수를 찾는다. + * 2. n보다 작거나 같은 소수들이 상근수인지 판단한다. + * 3. 소수이면서 상근수이면 결과값으로 추가한다. + */ + +int main() { + // 입력 + int n; + cin >> n; + + // 연산 + vector result = solution(n); + + // 출력 + for (int num : result) { + cout << num << "\n"; + } + return 0; +} diff --git "a/03_\354\240\225\354\210\230\353\241\240/\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/03_\354\240\225\354\210\230\353\241\240/\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/03_\354\240\225\354\210\230\353\241\240/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/16563.cpp" "b/03_\354\240\225\354\210\230\353\241\240/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/16563.cpp" new file mode 100644 index 00000000..9adb3b4e --- /dev/null +++ "b/03_\354\240\225\354\210\230\353\241\240/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/16563.cpp" @@ -0,0 +1,61 @@ +#include +#include + +const int MAX = 5000000; //k의 최대 범위 +using namespace std; + +vector getPrimes() { + vector primes(MAX + 1, 0); + for(int i = 2; i * i <= MAX; i++) { + if(primes[i] != 0) { //소수가 아니면 탐색 X + continue; + } + + //j의 가장 작은 소인수는 i + for(int j = i * i; j <= MAX; j += i) { + if (primes[j] == 0) { + primes[j] = i; + } + } + } + return primes; +} +vector getPrimeFactors(int k, vector &primes) { + vector factors; //소인수 저장 + + while(primes[k] != 0) { //k가 소수가 될 때까지 + factors.push_back(primes[k]); + k /= primes[k]; + } + factors.push_back(k); + return factors; +} +int main() { + //입출력 속도 향상 + ios::sync_with_stdio(false); + cin.tie(NULL); + cout.tie(NULL); + + //입력 + int n, k; + cin>>n; + + //소수 경로 구하기 + vector primes = getPrimes(); + + //n개의 케이스 입력 + while (n--) { + cin >> k; + + //소인수분해 + vector factors = getPrimeFactors(k, primes); + + //출력 + for (int num : factors) { + cout << num << " "; + } + cout << "\n"; + } + + return 0; +} \ No newline at end of file diff --git "a/03_\354\240\225\354\210\230\353\241\240/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2609.cpp" "b/03_\354\240\225\354\210\230\353\241\240/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2609.cpp" new file mode 100644 index 00000000..c276e8a8 --- /dev/null +++ "b/03_\354\240\225\354\210\230\353\241\240/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2609.cpp" @@ -0,0 +1,49 @@ +#include +#include + +using namespace std; + +//O(n)으로 최대공약수(gcd) 구하기 +int getGcdBad(int a, int b) { + for (int i = min(a, b); i > 0; i--) { + //i가 a의 약수이자 b의 약수이면 -> i는 공약수 + if (a % i == 0 && b % i == 0) { + return i; + } + } + return 1; +} + +//재귀 이용하여 최대공약수(gcd) 구하기 +int getGcdRecur(int a, int b) { + if (b == 0) { + return a; + } + return getGcdRecur(b, a%b); +} + +//반복문 이용하여 최대공약수(gcd) 구하기 +int getGcdIter(int a, int b) { + int tmp; + while (b != 0) { + tmp = a % b; + a = b; + b = tmp; + } + return a; +} + +int main() { + //입력 + int a, b; + cin >> a >> b; + + //최대공약수 + int gcd = getGcdRecur(max(a, b), min(a, b)); + //최소공배수 + int lcm = a * b / gcd; + + //출력 + cout << gcd << "\n" << lcm; + return 0; +} \ No newline at end of file diff --git "a/03_\354\240\225\354\210\230\353\241\240/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2960.cpp" "b/03_\354\240\225\354\210\230\353\241\240/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2960.cpp" new file mode 100644 index 00000000..51687a6b --- /dev/null +++ "b/03_\354\240\225\354\210\230\353\241\240/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2960.cpp" @@ -0,0 +1,36 @@ +#include +#include + +using namespace std; + +int findPrime(int n, int k) { + vector is_prime(n + 1, true); //소수 여부 저장 + int cnt = 0; //현재 지워진 수의 개수 저장 + + for (int i = 2; i <= n; i++) { + if (!is_prime[i]) { //이미 지워진 수이면 탐색 X + continue; + } + for (int j = i; j <= n; j += i) { + if (!is_prime[j]) { //이미 지워진 수이면 탐색 X + continue; + } + if ((++cnt) == k) { + //지금 지워지는 수가 k번째 지워지는 수이면 현재 수 반환 + return j; + } + is_prime[j] = false; //현재 수 지우기 + } + } + return -1; +} +int main() { + //입력 + int n, k, cnt = 0; + cin >> n >> k; + + //출력 + cout << findPrime(n, k); + + return 0; +} \ No newline at end of file diff --git "a/03_\354\240\225\354\210\230\353\241\240/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" "b/03_\354\240\225\354\210\230\353\241\240/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\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/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/1735.cpp" "b/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/1735.cpp" new file mode 100644 index 00000000..beb65fe9 --- /dev/null +++ "b/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/1735.cpp" @@ -0,0 +1,35 @@ +#include + +using namespace std; + +// 최대공약수(GCD) 계산 함수: 유클리드 호제법 이용 +int getGCD(int a, int b) { + if (b == 0) return a; + return getGCD(b, a % b); +} + +/* [백준 1735: 분수 합] + * a/b + c/d = (a*d)/(b*d) + (b*c)/(b*d) = (a*d + b*c)/(b*d) + * 위 분수를 기약분수로 나타낸 것을 x/y라 하고, + * gcd를 (a*d + b*c)와 (b*d)의 최대공약수라 하면 + * x = (a*d + b*c) / gcd + * y = (b*d) / gcd +*/ + +int main() { + // 입력 + int a, b, c, d; + cin >> a >> b >> c >> d; + + // 연산 + int x = (a * d) + (b * c); // 분자 + int y = b * d; // 분모 + int gcd = getGCD(x, y); + x = x / gcd; // 기약분수의 분자 + y = y / gcd; // 기약분수의 분모 + + // 출력 + cout << x << " " << y; + + return 0; +} diff --git "a/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/2840_v1.cpp" "b/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/2840_v1.cpp" new file mode 100644 index 00000000..59d34724 --- /dev/null +++ "b/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/2840_v1.cpp" @@ -0,0 +1,76 @@ +#include +#include + +using namespace std; + +typedef pair ci; +const int ALPHA = 26; + +/* + [2840 행운의 바퀴 ver1] + - 문제에서 주어진대로 화살표를 고정시키고, 바퀴를 시계방향으로 돌려서 문제를 푼다. + - 배열을 ?로 초기화 해주고, 입력한대로 처리한다 + - 바퀴를 배열로 보고 시계방향으로 바퀴를 회전시키면, 화살표가 가리키고 있는 배열의 원소는 인덱스가 감소하는 것처럼 + 보인다. + <주의 사항> + 1. ?이 아닌 문자가 저장되어있는데, 다른 문자를 저장하려는 경우 + 2. 룰렛에 중복되는 문자가 있는 경우 + ** 바퀴를 돌리는 횟수가 매우 클 수도 있다. 이 부분을 유의하여 인덱스를 처리하자! + ex) n=3 인데, 바퀴를 10번 돌릴수도 있다. +*/ + +// 특정 화살표에서 시작한 행운의 바퀴 리턴 +string arrowStartWheel(int index, int n, vector &wheel) { + string ans = ""; + + for (int i = 0; i < n; i++) { + ans += wheel[(i + index) % n]; + } + + return ans; +} + +string makeWheel(int n, vector &record) { + vector wheel(n, '?'); //?로 초기화 + vector is_available(ALPHA, false); // 알파벳 중복 체크 + + int index = 0; // 화살표가 가리키는 인덱스 + + for (int i = 0; i < record.size(); i++) { + int rot = record[i].first; + int ch = record[i].second; + + index = (index - rot + 100 * n) % n; + + if (wheel[index] == ch) { + continue; + } + + // 주의사항 체크 + // 원판의 해당 위치에 다른 문자가 저장되어있거나, 이미 다른 곳에 문자가 사용된 경우 + if (wheel[index] != '?' || is_available[ch - 'A']) { + return "!"; + } + + wheel[index] = ch; // 원판에 기록 + is_available[ch - 'A'] = true; // 알파벳 사용을 표시 + } + + return arrowStartWheel(index, n, wheel); +} + +int main() { + // 입력 + int n, k; + cin >> n >> k; + + vector record(k, {0, 0}); // 바퀴 회전 기록 + for (int i = 0; i < k; i++) { + cin >> record[i].first >> record[i].second; + } + + // 출력 + cout << makeWheel(n, record); + + return 0; +} \ No newline at end of file diff --git "a/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/2840_v2.cpp" "b/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/2840_v2.cpp" new file mode 100644 index 00000000..1563d2a0 --- /dev/null +++ "b/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/2840_v2.cpp" @@ -0,0 +1,73 @@ +#include +#include + +using namespace std; + +typedef pair ci; +const int ALPHA = 26; + +/* + [2840 행운의 바퀴 ver2] + - 화살표를 이동시키는 방식으로 문제를 푼다. + - 이후 출력시 방향을 바꾸어 출력한다. + - 배열을 ?로 초기화 해주고, 입력대로 처리한다 + <주의 사항> + 1. ?이 아닌 문자가 저장되어있는데, 다른 문자를 저장하려는 경우 + 2. 룰렛에 중복되는 문자가 있는 경우 +*/ + +// 특정 화살표에서 시작한 행운의 바퀴 리턴 +string arrowStartWheel(int index, int n, vector &wheel) { + string ans = ""; + + for (int i = n; i > 0; i--) { + ans += wheel[(i + index) % n]; + } + + return ans; +} + +string makeWheel(int n, vector &record) { + vector wheel(n, '?'); //?로 초기화 + vector is_available(ALPHA, false); // 알파벳 중복 체크 + + int index = 0; // 화살표가 가리키는 인덱스 + + for (int i = 0; i < record.size(); i++) { + int rot = record[i].first; + int ch = record[i].second; + + index = (index + rot) % n; // 화살표 이동 + + if (wheel[index] == ch) { + continue; + } + + // 주의사항 체크 + // 다른 문자가 저장되어있거나, 이미 다른 곳에 문자가 사용된 경우 + if (wheel[index] != '?' || is_available[ch - 'A']) { + return "!"; + } + + wheel[index] = ch; // 원판에 기록 + is_available[ch - 'A'] = true; // 알파벳 사용을 표시 + } + + return arrowStartWheel(index, n, wheel); +} + +int main() { + // 입력 + int n, k; + cin >> n >> k; + + vector record(k, {0, 0}); // 바퀴 회전 기록 + for (int i = 0; i < k; i++) { + cin >> record[i].first >> record[i].second; + } + + // 출력 + cout << makeWheel(n, record); + + return 0; +} diff --git "a/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/6588.cpp" "b/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/6588.cpp" new file mode 100644 index 00000000..fb7c19b2 --- /dev/null +++ "b/03_\354\240\225\354\210\230\353\241\240/\355\225\204\354\210\230/6588.cpp" @@ -0,0 +1,68 @@ +#include +#include +#include + +using namespace std; + +// 소수 여부 반환 함수: 에라토스테네스의 체 이용 +vector getPrimes(int n) { + vector is_prime(n + 1, true); + is_prime[0] = is_prime[1] = false; + for (int i = 2; i * i <= n; i++) { + if (!is_prime[i]) { + continue; + } + for (int j = i * i; j <= n; j += i) { + is_prime[j] = false; + } + } + return is_prime; +} + +// n = a + b를 만족시키는 a 반환 +int goldbach(int n, vector &is_prime) { + for (int a = 3; a <= n / 2; a+= 2) { + // 2보다 큰 짝수 소수는 존재하지 않으므로 + // a = 3부터 탐색해도 a와 b 모두 홀수여야 한다는 조건 만족 + if (is_prime[a] && is_prime[n - a]) { + return a; + } + } + // n = a + b를 만족시키는 홀수 소수 a, b가 없으면 0 반환 + return 0; +} + +/* [백준 6588: 골드바흐의 추측] + * 1. 3보다 크거나 같고 n / 2보다 작거나 같은 소수 a를 오름차순으로 탐색한다. + * 2. 1에서 찾은 a에 대하여 n - a(=b)도 소수이면 골드바흐의 추측이 성립한다. + * 3. 골드바흐의 추측이 성립하면 a를, 성립하지 않으면 0을 반환한다. + */ + +int main() { + // 입력 + vector arr; + int input; + while(1) { + cin >> input; + if (input == 0) { + break; + } + arr.push_back(input); + } + + // 연산 + int max_num = *max_element(arr.begin(), arr.end()); + vector is_prime = getPrimes(max_num); + + for (int i = 0; i < arr.size(); i++) { + int a = goldbach(arr[i], is_prime); + + // 출력 + if (a != 0) { // n = a + b를 만족하는 a, b가 존재하면 + cout << arr[i] << " = " << a << " + " << arr[i] - a << "\n"; + } else { // 존재하지 않으면 + cout << "Goldbach's conjecture is wrong.\n"; + } + } + return 0; +} diff --git "a/03_\354\240\225\354\210\230\353\241\240/\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/03_\354\240\225\354\210\230\353\241\240/\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/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/README.md" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/README.md" index e69de29b..207c4c26 100644 --- "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/README.md" +++ "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/README.md" @@ -0,0 +1,77 @@ +# 브루트 포스 (Brute Force) + +[메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4) + +## 💻 튜터링 + +### 라이브 코딩 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :---------------------------------------------------------------------: | :----------------------------------------------------------------------------: | :-------------------------------------------------------------------------------: | :----------: | :---------------: | +| 2309 | 일곱 난쟁이 | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/04_%EB%B8%8C%EB%A3%A8%ED%8A%B8%20%ED%8F%AC%EC%8A%A4/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/2309.cpp) | 브루트 포스, 정렬 | +| 2231 | 분해합 | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/04_%EB%B8%8C%EB%A3%A8%ED%8A%B8%20%ED%8F%AC%EC%8A%A4/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/2231.cpp) | 브루트 포스 | + +## ✏️ 과제 + +### 마감기한 + +~ 3 / 14 (화) 18:59 - 과제 제출
+~ 3 / 16 (목) 23:59 - 추가 제출
+ +### 필수 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :---------------------------------------------------------------------: | :----------------------------------------------------------------------------: | :-------------------------------------------------------------------------------: | :-------: | :--------------: | +| 1063 | | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/04_%EB%B8%8C%EB%A3%A8%ED%8A%B8%20%ED%8F%AC%EC%8A%A4/%ED%95%84%EC%88%98/1063.cpp) | 구현, 시뮬레이션 | +| 1436 | 영화감독 숌 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/04_%EB%B8%8C%EB%A3%A8%ED%8A%B8%20%ED%8F%AC%EC%8A%A4/%ED%95%84%EC%88%98/1436.cpp) | 브루트 포스 | +| 1065 | 한수 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/04_%EB%B8%8C%EB%A3%A8%ED%8A%B8%20%ED%8F%AC%EC%8A%A4/%ED%95%84%EC%88%98/1065.cpp) | 브루트 포스 | + +### 도전 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :-------------------------------------------------------------------------: | :-------------------------------------------------------------------------------: | :-------: | :---------: | +| 14620 | 꽃길 | | [C++_v1](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/04_%EB%B8%8C%EB%A3%A8%ED%8A%B8%20%ED%8F%AC%EC%8A%A4/%EB%8F%84%EC%A0%84/14620_v1.cpp)
[C++_v2](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/04_%EB%B8%8C%EB%A3%A8%ED%8A%B8%20%ED%8F%AC%EC%8A%A4/%EB%8F%84%EC%A0%84/14620_v2.cpp) | 브루트 포스 | +| 3085 | 사탕게임 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/04_%EB%B8%8C%EB%A3%A8%ED%8A%B8%20%ED%8F%AC%EC%8A%A4/%EB%8F%84%EC%A0%84/3085.cpp) | 브루트 포스 | + +--- + +### 힌트 + +
+ +
+    문자형 변수의 연산은 비교적 자유로워요! 또 킹과 돌의 움직임이 모두 판 안에서 이뤄질 때만 다음으로 움직일 수 있는 점을 신경써주세요! +
+
+ +
+영화감독 숌 +
+    각 숫자마다 6이 세 개 이상 연속되는지 확인해보세요. 숫자가 어렵다면 문자열로 바꿔도 괜찮을 것 같네요! +
+
+ +
+한수 +
+    각 숫자마다 자리 수들이 등차 수열인지 확인해보세요. 숫자가 어렵다면 문자열로 바꿔도 괜찮을 것 같네요! +
+
+ +
+꽃길 +
+    그래프의 크기가 최대 10 x 10 이네요? 세개의 꽃을 심을 수 있는 모든 경우의 수를 탐색해보아도 괜찮겠어요. 꽃이 피는 자리가 그래프의 테두리에 있는 경우는 없네요. +씨앗을 다 심었다면 특정 위치에 씨앗을 심을 경우 5칸의 비용이 얼마인지를 알아야하고, 또 그렇게 씨앗을 심었을때 꽃잎이 죽지 않는지를 판단해야겠네요! + +
+
+ +
+사탕게임 +
+    범위가 크지 않으니 바꿀 수 있는 사탕을 하나하나 다 바꿔봐도 좋아요. 각 행과 열에서 먹을 수 있는 사탕의 수를 세는게 중요하겠네요. +
+
+ +--- diff --git "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\352\260\225\354\235\230 \354\236\220\353\243\214/04_\353\270\214\353\243\250\355\212\270\355\217\254\354\212\244_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\352\260\225\354\235\230 \354\236\220\353\243\214/04_\353\270\214\353\243\250\355\212\270\355\217\254\354\212\244_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" new file mode 100644 index 00000000..258e2633 Binary files /dev/null and "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\352\260\225\354\235\230 \354\236\220\353\243\214/04_\353\270\214\353\243\250\355\212\270\355\217\254\354\212\244_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" differ diff --git "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\352\260\225\354\235\230 \354\236\220\353\243\214/04_\353\270\214\353\243\250\355\212\270\355\217\254\354\212\244_\354\235\264\353\241\240.pdf" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\352\260\225\354\235\230 \354\236\220\353\243\214/04_\353\270\214\353\243\250\355\212\270\355\217\254\354\212\244_\354\235\264\353\241\240.pdf" new file mode 100644 index 00000000..1a1870aa Binary files /dev/null and "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\352\260\225\354\235\230 \354\236\220\353\243\214/04_\353\270\214\353\243\250\355\212\270\355\217\254\354\212\244_\354\235\264\353\241\240.pdf" differ diff --git "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\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/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\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/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\217\204\354\240\204/14620_v1.cpp" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\217\204\354\240\204/14620_v1.cpp" new file mode 100644 index 00000000..c91f32a7 --- /dev/null +++ "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\217\204\354\240\204/14620_v1.cpp" @@ -0,0 +1,58 @@ +#include +#include +#include + +using namespace std; +const int MAX_N = 11; +const int MAX_ANS = 200 * 15; + +int getScore(int r, int c, vector> gr) { + return gr[r - 1][c] + gr[r][c - 1] + gr[r + 1][c] + gr[r][c + 1] + gr[r][c]; +} + +int solution(int n, vector> gr) { + int answer = MAX_ANS; + int r1, c1, r2, c2, r3, c3; + n -= 2; + + for (int i = 0; i < n * n; i++) { //씨앗을 심을 세 곳의 할당값(r,c)을 선택 + r1 = i / n + 1; c1 = i % n + 1; // 할당값으로 행과 열 계산 + for (int j = 0; j < n * n; j++) { + r2 = j / n + 1; c2 = j % n + 1; + if (abs(r1 - r2) + abs(c1 - c2) <= 2) { + continue; //겹치는 경우 제외 + } + for (int t = 0; t < n * n; t++) { + r3 = t / n + 1; c3 = t % n + 1; + if (abs(r1 - r3) + abs(c1 - c3) <= 2 || abs(r2 - r3) + abs(c2 - c3) <= 2) { + continue;//겹치는 경우 제외 + } + answer = min(answer, getScore(r1, c1, gr) + getScore(r2, c2, gr) + getScore(r3, c3, gr)); //합산 + } + } + } + return answer; +} +/* 꽃길 14620 + * 테투리를 제외한 칸 (n-2) * (n-2) 칸 중에 3칸을 고르면 됩니다. + * 3칸 중 어떤 두 칸 (r1,c1), (r2,c2)가 abs(r1 - r2) + abs(c1 - c2) <= 2 인 경우를 제외시키면 됩니다. + *! 칸을 고를 때, (n-2) * (n-2) 크기의 판에 순서대로 0 ~ (n-2)*(n-2) - 1 만큼의 숫자를 할당했다고 가정합시다. + *! 그러면 어떤 칸이 x (0 <= x < (n-2)*(n-2))값을 가진다면, 그 칸의 행(r)은 x / (n-2) + 1 이고 열(c)은 x % (n-2) + 1 입니다. + *! 이 방법이 어렵다면 6중 반복문으로 행과 열을 골라주어도 됩니다. + */ +int main() +{ + int n; + vector> gr(MAX_N, vector(MAX_N)); + //입력 + cin >> n; + + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + cin >> gr[i][j]; + } + } + //연산 & 출력 + cout << solution(n, gr); + return 0; +} \ No newline at end of file diff --git "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\217\204\354\240\204/14620_v2.cpp" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\217\204\354\240\204/14620_v2.cpp" new file mode 100644 index 00000000..f961059f --- /dev/null +++ "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\217\204\354\240\204/14620_v2.cpp" @@ -0,0 +1,80 @@ +#include +#include +#include + +using namespace std; +const int MAX = 3000; + +vector> board; +vector> check; +int dr[5] = { 0, -1, 1, 0, 0 }; +int dc[5] = { 0, 0, 0, -1, 1 }; +int ans = MAX; + +int chkFlower(int r, int c) { + + int sum = 0; + for (int i = 0; i < 5; i++) { + int nr = r + dr[i]; + int nc = c + dc[i]; + if (check[nr][nc]) { // 이미 꽃 있다면 + return -1; + } + sum += board[nr][nc]; + } + return sum; +} +void plant(int r, int c, bool marking_type) { //상하좌우로 꽃 심거나 돌려놓기. + + + for (int i = 0; i < 5; i++) { + int nr = r + dr[i]; + int nc = c + dc[i]; + + check[nr][nc] = marking_type; + } + +} +void minFlower(int cnt, int sum) { + + if (cnt == 3) { + ans = min(ans, sum); + return; + } + for (int i = 1; i < board.size() - 1; i++) { + for (int j = 1; j < board.size() - 1; j++) { + int sumFlower = chkFlower(i, j); + if (sumFlower == -1) { + continue; + } + plant(i, j, 1); + minFlower(cnt + 1, sum + sumFlower); + plant(i, j, 0); + } + } +} +/* 꽃길 14620 백트랙킹 버전 + 백트랙킹을 공부하고 나서 다시 풀어보세요~ +*/ + +int main() { + + int n; + + // 입력 + cin >> n; + + board.assign(n, vector(n, 0)); + check.assign(n, vector(n, false)); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + cin >> board[i][j]; + } + } + + // 연산 & 출력 + minFlower(0, 0); + + cout << ans; + return 0; +} \ No newline at end of file diff --git "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\217\204\354\240\204/3085.cpp" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\217\204\354\240\204/3085.cpp" new file mode 100644 index 00000000..1a9d55f0 --- /dev/null +++ "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\217\204\354\240\204/3085.cpp" @@ -0,0 +1,73 @@ +#include +#include +#include + +using namespace std; + +/* +입력 범위가 작으므로, 사탕을 전부 바꿔보며 계산하자 +*/ + +int n; +vector arr; +int dr[2] = {1, 0}; +int dc[2] = {0, 1}; + +int countCandy(int row, int col, int dir) { + int result = 0, cnt = 0; + char prev = ' '; + for (int i = 0; i < n; i++) { + if (prev == arr[row][col]) { //연속된 사탕 + cnt++; + result = max(result, cnt); + } else { //불연속 + cnt = 1; + prev = arr[row][col]; + } + row += dr[dir]; + col += dc[dir]; + } + return result; +} + +int findCandy() { + int result = 0; + for (int i = 0; i < n; i++) { + result = max(result, countCandy(0, i, 0)); //같은 열 + result = max(result, countCandy(i, 0, 1)); //같은 행 + } + return result; +} + +int switchCandy(int row, int col, char candy) { + int result = 0; + for (int i = 0; i < 2; i++) { + int nr = row + dr[i], nc = col + dc[i]; + if (nr < n && nc < n && candy != arr[nr][nc]) { + swap(arr[row][col], arr[nr][nc]); + result = max(result, findCandy()); + swap(arr[row][col], arr[nr][nc]); + } + } + return result; +} + +int main() { + // 입력 + cin >> n; + arr.assign(n, ""); + for (int i = 0; i < n; i++) { + cin >> arr[i]; + } + // 연산 + int result = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + result = max(result, switchCandy(i, j, arr[i][j])); + } + } + + // 출력 + cout << result; + return 0; +} diff --git "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\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/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\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/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2231.cpp" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2231.cpp" new file mode 100644 index 00000000..78d3546c --- /dev/null +++ "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2231.cpp" @@ -0,0 +1,24 @@ +#include +#include + +using namespace std; + +int main() { + int answer = 0, n; + //입력 + cin >> n; + //연산 + for (int i = 1; i < n; i++) { + string s = to_string(i); + int sum_num = i; + for (int j = 0; j < s.size(); j++) { + sum_num += s[j] - '0'; + } + if (sum_num == n) { + answer = i; + break; + } + } + //출력 + cout << answer; +} diff --git "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2309.cpp" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2309.cpp" new file mode 100644 index 00000000..2e0a0555 --- /dev/null +++ "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2309.cpp" @@ -0,0 +1,31 @@ +#include +#include +#include + +using namespace std; + +int main() +{ + int n = 9, sum_height = 0, num; + vector v; + //입력 + while (n--) { + cin >> num; + v.push_back(num); + sum_height += num; + } + sort(v.begin(), v.end()); //정렬 + //연산 & 출력 + for (int i = 0; i < 8; i++) { + for (int j = i + 1; j < 9; j++) { + if (sum_height - v[i] - v[j] == 100) { + for (int k = 0; k < 9; k++) { + if (k != i && k != j) { + cout << v[k] << '\n'; + } + } + return 0; + } + } + } +} diff --git "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\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/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\355\225\204\354\210\230/1063.cpp" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\355\225\204\354\210\230/1063.cpp" new file mode 100644 index 00000000..38c639bc --- /dev/null +++ "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\355\225\204\354\210\230/1063.cpp" @@ -0,0 +1,90 @@ +#include +#include +#include + +using namespace std; +typedef paircc; + +cc move(string input, char x, char y) {//이동 함수 x : 열, y : 행 + for (int i = 0; i < input.size(); i++) { + char how = input[i]; + if (how == 'R') { + x++; + } + else if (how == 'L') { + x--; + } + else if (how == 'B') { + y--; + } + else {//T + y++; + + } + } + + return { x, y }; + +} + +bool checkRange(cc position) {//범위 체크 하는 함수 + + if (position.first < 'A' || position.first > 'H' + || position.second < '1' || position.second > '8') { + return false; + } + + return true; +} + +bool isSame(cc k, cc s) { + + return (k.first == s.first && k.second == s.second); + +} + +/* +* HINT : 문자형 변수의 연산은 비교적 자유로워요! 또 킹과 돌의 움직임이 모두 판 안에서 이뤄질 때만 다음으로 움직일 수 있는 점을 신경써주세요! +* 1. king 이동 (move) +* 2. king과 stone의 위치 동일 -> stone 이동 (move) +* 3. king과 stone의 위치 점검 (checkRange +*/ + +int main() { + + cc k, s;//king, stone + int n; + string input; + + //입력 + cin >> k.first >> k.second >> s.first >> s.second >> n; + + //연산 + while (n--) { + cin >> input; + + cc next_k, next_s;//이동 후 위치 저장할 변수 + + //king 이동 + next_k = move(input, k.first, k.second); + + //stone 이동 + if (isSame(next_k,s)) { + next_s = move(input, s.first, s.second); + } + else { + next_s = s; + } + + //범위 체크 + if (checkRange(next_k) && checkRange(next_s)){//이동한 king과 stone가 유효 범위면 최종적으로 이동 + k = next_k; + s = next_s; + } + + } + + //출력 + cout << k.first << k.second <<'\n'<< s.first << s.second ; + return 0; +} \ No newline at end of file diff --git "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\355\225\204\354\210\230/1065.cpp" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\355\225\204\354\210\230/1065.cpp" new file mode 100644 index 00000000..29c72a7e --- /dev/null +++ "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\355\225\204\354\210\230/1065.cpp" @@ -0,0 +1,33 @@ +#include +#include + +using namespace std; + +int solution(int num) { + int cnt = 99; // 100 미만의 숫자는 그 자체로 등차수열이다 + for (int i = 100; i <= num; i++) { + int hun = i / 100; // 백의 자릿수 + int ten = (i / 10) % 10; // 십의 자릿수 + int one = i % 10; + + if ((hun - ten) == (ten - one)) { // 각 자릿수가 수열을 이루면 + cnt++; + } + } + return cnt; +} + +int main() +{ + int n; + //입력 + cin >> n; + //연산 & 출력 + if (n <= 99) { + cout << n; + } + else { + cout << solution(n); + } + return 0; +} diff --git "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\355\225\204\354\210\230/1436.cpp" "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\355\225\204\354\210\230/1436.cpp" new file mode 100644 index 00000000..6606c2d9 --- /dev/null +++ "b/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\355\225\204\354\210\230/1436.cpp" @@ -0,0 +1,40 @@ +#include +#include + +using namespace std; + +int main() +{ + int n, cnt = 0; + //입력 + cin >> n; + //연산 & 출력 + for (int i = 666; i < 2066666666; i++) { + // 방법 1 + string s = to_string(i); + int suc = 0; // 연속하는 6의 개수 + for (int j = 0; j < s.length(); j++) { + if (s[j] == '6') { + suc++; + } + else { + suc = 0; + } + if (suc == 3) { + cnt++; + break; + } + } + /* + * 방법 2 + * s.substr(j, 3) == "666" + * substr 사용법 : https://en.cppreference.com/w/cpp/string/basic_string/substr + * 방법 3 + * if (s.find("666") != -1) + * find 사용법 : https://en.cppreference.com/w/cpp/string/basic_string/find + */ + if (cnt == n) { + return cout << s, 0; + } + } +} \ No newline at end of file diff --git "a/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\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/04_\353\270\214\353\243\250\355\212\270 \355\217\254\354\212\244/\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/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/README.md" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/README.md" index e69de29b..1e1bc161 100644 --- "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/README.md" +++ "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/README.md" @@ -0,0 +1,75 @@ +# 우선순위 큐 (Priority Queue) + +[메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4) + +## 💻 튜터링 + +### 라이브 코딩 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :---------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :----------: | :---------: | +| 11279 | 최대 힙 | | [바로가기1](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/05_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%20%ED%81%90/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/11279_v1.cpp)
[바로가기2](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/05_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%20%ED%81%90/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/11279_v2.cpp) | 우선순위 큐 | +| 11286 | 절댓값 힙 | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/05_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%20%ED%81%90/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/11286.cpp) | 우선순위 큐 | + +## ✏️ 과제 + +### 마감기한 + +~ 3 / 21 (화) 18:59 - 과제 제출
+~ 3 / 23 (목) 23:59 - 추가 제출
+ +### 필수 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :---------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------: | :-------: | :---------------: | +| 2607 | 비슷한 단어 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/05_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%20%ED%81%90/%ED%95%84%EC%88%98/2607.cpp) | 구현, 문자열 | +| 14235 | 크리스마스 선물 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/05_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%20%ED%81%90/%ED%95%84%EC%88%98/14235.cpp) | 우선순위 큐 | +| 2075 | N번째 큰 수 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/05_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%20%ED%81%90/%ED%95%84%EC%88%98/2075.cpp) | 우선순위 큐, 정렬 | + +### 도전 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :--------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :---------: | +| 프로그래머스 | 디스크 컨트롤러 | **Lv.3** | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/05_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%20%ED%81%90/%EB%8F%84%EC%A0%84/%EB%94%94%EC%8A%A4%ED%81%AC%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC.cpp) | 우선순위 큐 | +| 1655 | 가운데를 말해요 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/05_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%20%ED%81%90/%EB%8F%84%EC%A0%84/1655.cpp) | 우선순위 큐 | + +--- + +### 힌트 + +
+비슷한 단어 +
+    문제의 조건대로 구현해주시면 됩니다 :) +
+
+ +
+크리스마스 선물 +
+    아이들에게 주는 선물의 특징을 고려해 자료구조를 선택해보세요! +
+
+ +
+N번째 큰 수 +
+    상위 n개의 숫자에서 n번째 숫자는 가장 작은 숫자네요! +
+
+ +
+디스크 컨트롤러 +
+    현재 시각에서 요청된 task 중 소요시간이 가장 적은 task를 우선으로 실행해야 해요! 시간이 흘러감에 따라 수행돼야 하는 기능을 생각해보세요! +
+
+ +
+가운데를 말해요 +
+    가운데를 찾기 위해 현재까지 입력된 숫자 중 비교적 작은 값과 큰 값을 따로 저장하면 좋을 것 같네요! +
+
+ +--- diff --git "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\352\260\225\354\235\230 \354\236\220\353\243\214/05_\354\232\260\354\204\240\354\210\234\354\234\204\355\201\220_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\352\260\225\354\235\230 \354\236\220\353\243\214/05_\354\232\260\354\204\240\354\210\234\354\234\204\355\201\220_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" new file mode 100644 index 00000000..218d86df Binary files /dev/null and "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\352\260\225\354\235\230 \354\236\220\353\243\214/05_\354\232\260\354\204\240\354\210\234\354\234\204\355\201\220_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" differ diff --git "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\352\260\225\354\235\230 \354\236\220\353\243\214/05_\354\232\260\354\204\240\354\210\234\354\234\204\355\201\220_\354\235\264\353\241\240.pdf" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\352\260\225\354\235\230 \354\236\220\353\243\214/05_\354\232\260\354\204\240\354\210\234\354\234\204\355\201\220_\354\235\264\353\241\240.pdf" new file mode 100644 index 00000000..82156e2e Binary files /dev/null and "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\352\260\225\354\235\230 \354\236\220\353\243\214/05_\354\232\260\354\204\240\354\210\234\354\234\204\355\201\220_\354\235\264\353\241\240.pdf" differ diff --git "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\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/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\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/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\217\204\354\240\204/1655.cpp" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\217\204\354\240\204/1655.cpp" new file mode 100644 index 00000000..7e961d59 --- /dev/null +++ "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\217\204\354\240\204/1655.cpp" @@ -0,0 +1,72 @@ +#include +#include +#include + +using namespace std; + +/* +* HINT : 가운데를 찾기 위해 현재까지 입력된 숫자중 비교적 작은 값과 큰 값을 따로 저장하면 좋을 것 같네요! +*/ + +void balance(priority_queue& max_pq, + priority_queue, greater<>>& min_pq) { + int M, m; + + if (max_pq.top() > min_pq.top()) { // max_pq의 가장 큰 값이 min_pq의 가장 작은 값보다 크다면 저장 위치가 잘못된 것! + // 각각의 top값을 바꿔서 저장 + M = max_pq.top(); + m = min_pq.top(); + + max_pq.pop(); + min_pq.pop(); + + max_pq.push(m); + min_pq.push(M); + } + + return; +} + +/* +* 입력된 수들 중 비교적 작은 값은 최대힙에 저장하고 큰 값은 최소힙에 저장하자 +* 가운데를 찾기 위해서는 최대힙과 최소힙 개수 차이가 0이나 1이어야 한다 +* 최대힙의 top값이 가운데이도록 하기 위해 최대힙의 사이즈가 최소힙의 사이즈와 같거나 1 더 크게 저장하자 +* 개수를 기준으로 저장했기에 저장 위치가 잘못됐을 수도 있다. -> 균형을 맞춰주자 (balance) +*/ + +int main() { + + ios_base::sync_with_stdio(false); + cin.tie(NULL); + cout.tie(NULL); + + int n, input; + priority_queue max_pq; // 비교적 작은 값을 저장해둔 최대힙 + priority_queue, greater<>> min_pq; // 비교적 큰 값을 저장해둔 최소힙 + + // 입력 + cin >> n; + + // 연산 + 출력 + for (int i = 0; i < n; i++) { + cin >> input; + + // max_pq의 사이즈가 min_pq의 사이즈와 같거나 하나 더 많도록 저장 + if (max_pq.size() > min_pq.size()) { + min_pq.push(input); + } + else { + max_pq.push(input); + } + + // 두 개의 pq모두 원소가 존재할 때 균형을 맞춰주자 + if (!max_pq.empty() && !min_pq.empty()) { + balance(max_pq, min_pq); + } + + // 출력 + cout << max_pq.top() << "\n"; + + } + return 0; +} \ No newline at end of file diff --git "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\217\204\354\240\204/\353\224\224\354\212\244\355\201\254_\354\273\250\355\212\270\353\241\244\353\237\254.cpp" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\217\204\354\240\204/\353\224\224\354\212\244\355\201\254_\354\273\250\355\212\270\353\241\244\353\237\254.cpp" new file mode 100644 index 00000000..dc288f44 --- /dev/null +++ "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\217\204\354\240\204/\353\224\224\354\212\244\355\201\254_\354\273\250\355\212\270\353\241\244\353\237\254.cpp" @@ -0,0 +1,72 @@ +#include +#include +#include +#include + +using namespace std; + +// HINT : 현재 시각에서 요청된 task 중 소요시간이 가장 적은 task를 우선으로 실행해야 해요! 시간이 흘러감에 따라 수행돼야 하는 기능을 생각해보세요! + +struct sortMinTime { + bool operator()(vector a, vector b) { + return a[1] > b[1]; + } +}; + +int solution(vector> jobs) { // 요청시간, 소요시간 + int answer = 0; + int curt_time = 0; // 현재 시간 + int total_time = 0; // 대기 시간 + int next_request_job = 0; // 다음으로 요청되는 task 인덱스 번호 + int job_cnt = jobs.size(); + priority_queue, vector>, sortMinTime> pq; // 소요시간이 작은 순으로 정렬해주는 우선순위 큐 + + + sort(jobs.begin(), jobs.end()); // task를 요청 시간이 작은 순으로 정렬 + + + while (next_request_job < job_cnt || !pq.empty()) { + + // 현재 요청된 task는 없지만 task가 남아 있는 경우 + if (pq.empty()) { + curt_time = jobs[next_request_job][0]; + pq.push(jobs[next_request_job++]); + } + + // 현재 요청된 task 중 소요시간이 가장 적은 task 수행 + vector curt_job = pq.top(); + pq.pop(); + total_time += ((curt_time - curt_job[0]) + curt_job[1]); // (요청부터 실행까지 delay된 시간) + (요청부터 종료까지 total 시간) + curt_time += curt_job[1]; + + // 현재 시간까지 요청된 task를 큐에 push + while (next_request_job < job_cnt && jobs[next_request_job][0] <= curt_time) { + pq.push(jobs[next_request_job++]); + } + + } + answer = int(total_time / job_cnt); + + return answer; +} + +/* +* 1. 현재 시각에서 요청된 task 중 소요시간이 가장 적은 task를 우선으로 실행해야 한다! +* 2. pq의 top 에 있는 task를 수행함에 따라 total_time과 curt_time을 변경하자! +* 3. curt_time에 따라 요청된 task는 pq에 삽입하고 +*/ + +int main() { + vector> jobs; + int n; + cout << "task수 입력 : "; + cin >> n; + cout << "\ntask 요청시간 소요시간 입력(빈칸으로 구분)\n"; + while (n--) { + vector time(2); + cin >> time[0] >> time[1]; + jobs.push_back(time); + } + cout << solution(jobs); + return 0; +} \ No newline at end of file diff --git "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\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/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\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/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11279_v1.cpp" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11279_v1.cpp" new file mode 100644 index 00000000..b1090455 --- /dev/null +++ "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11279_v1.cpp" @@ -0,0 +1,35 @@ +#include +#include + +using namespace std; + +int main() { + + ios_base::sync_with_stdio(false); + cin.tie(NULL); + cout.tie(NULL); + + int n, x; + priority_queue max_heap; + + // 입력 + cin >> n; + + // 연산+출력 + while (n--) { + cin >> x; + if (x == 0) { + if (max_heap.empty()) { // 비어있다면 0출력 + cout << "0\n"; + } + else { // 가장 큰 값 출력하고 제거 + cout << max_heap.top() << '\n'; + max_heap.pop(); + } + } + else { // x삽입 + max_heap.push(x); + } + } + return 0; +} \ No newline at end of file diff --git "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11279_v2.cpp" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11279_v2.cpp" new file mode 100644 index 00000000..27118d7c --- /dev/null +++ "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11279_v2.cpp" @@ -0,0 +1,86 @@ +#include +#include + +using namespace std; + +// heap이 비어있는지 확인 +bool isEmpty(vector &heap) { + return heap.size() == 1; +} + +// heap에 x 삽입 +void push(vector &heap, int x) { + + // 0. 현재 힙의 크기 = 새로 push 할 데이터의 초기 인덱스 + int idx = heap.size(); + // 1. 힙의 마지막 자리에 x 삽입 + heap.push_back(x); + + // 부모노드와 비교하면서 바꿀 수 있을 때까지... + while (idx > 1 && heap[idx] > heap[idx / 2]) { + swap(heap[idx], heap[idx / 2]); // 부모노드와 swap + idx /= 2; // 현재 x가 위치한 인덱스 + } + return; +} + +// heap에서 값을 제거하고, 그 값을 리턴합 +int pop(vector &heap) { + // 우선 루트노드 값을 복사 + int item = heap[1]; + // 루트노트에 가장 뒤에 있는 값을 옮겨준다. + heap[1] = heap[heap.size() - 1]; + heap.pop_back(); // 데이터 제거 + + int size = heap.size(); // 힙의 크기 + int parent = 1, child = 2; + + // 자식노드가 존재하는 동안 비교 진행 + while (child < size) { + // 오른쪽 자식 노드가 존재한다면, 둘 중에 큰 쪽을 선택 + if (child + 1 < size && heap[child + 1] > heap[child]) { + child += 1; + } + + // 부모노드가 자식노드보다 값이 작은 경우 swap + if (heap[parent] < heap[child]) { + swap(heap[parent], heap[child]); + parent = child; + child = parent * 2; + } else { // 자식보다 부모노드가 큰 상황이므로 더 이상 swap은 필요 없음 + break; + } + } + return item; +} + +int main() { + // 입출력 속도 향상 + ios_base::sync_with_stdio(false); + cin.tie(NULL); + cout.tie(NULL); + + int n, x; + // 입력 + cin >> n; + + // heap 초기화 + vector heap_vec; + heap_vec.push_back(0); + + while (n--) { + cin >> x; + if (x == 0) { + // 비었다면 0 출력 + if (isEmpty(heap_vec)) { + cout << "0\n"; + } else { // 가장 큰 값 출력하고 제거 + cout << pop(heap_vec) << '\n'; + } + } else { + // 최대 힙에 x를 삽입 + push(heap_vec, x); + } + } + return 0; +} \ No newline at end of file diff --git "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11286.cpp" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11286.cpp" new file mode 100644 index 00000000..ced890ed --- /dev/null +++ "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11286.cpp" @@ -0,0 +1,47 @@ +#include +#include + +using namespace std; + +struct cmp { + bool operator()(const int& x1, const int& x2) { + if (abs(x2) != abs(x1)) { // 절댓값이 다르다면 절댓값 작은 수를 앞으로 + return abs(x2) < abs(x1); + } + return x2 < x1; // 절댓값이 동일하다면 값이 작은 수를 앞으로 + } +}; +/* +* 우선순위 기준 +* 1. 절댓값 작은 수 +* 2. 값이 작은 수 +*/ +int main() { + + ios_base::sync_with_stdio(false); + cin.tie(0); + cout.tie(0); + + int n, x; + priority_queue, cmp> pq; + cin >> n; + + while (n--) { + cin >> x; + + if (x == 0) { // 출력 + 삭제 + if (pq.empty()) { + cout << "0\n"; + } + else { + cout << pq.top() << '\n'; + pq.pop(); + } + + } + else { // 삽입 + pq.push(x); + } + } + return 0; +} \ No newline at end of file diff --git "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\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/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\355\225\204\354\210\230/14235.cpp" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\355\225\204\354\210\230/14235.cpp" new file mode 100644 index 00000000..8a0f2cb3 --- /dev/null +++ "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\355\225\204\354\210\230/14235.cpp" @@ -0,0 +1,50 @@ +#include +#include + +using namespace std; + +/* +* HINT : 아이들에게 주는 선물의 특징을 고려해 자료구조를 선택해봐요! +*/ + +/* + * 아이들에게 주는 선물 : 가치가 가장 큰 선물 -> 선물을 우선순위 큐에 저장 + * 1. 아이들을 만난 경우 + * 1) 큐가 비어있으면 -1 출력 + * 2) 큐의 top값 출력 + * 2. 선물 충전 -> 큐에 삽입 + */ +int main() { + + ios_base::sync_with_stdio(false); + cin.tie(NULL); + cout.tie(NULL); + + int n, input, gift; + priority_queue pq; + + // 입력 + cin >> n; + + // 연산 + 출력 + while (n--) { + + cin >> input; + if (!input) { // 아이들을 만난 경우 + if (pq.empty()) { + cout << "-1\n"; + } + else { + cout << pq.top() << '\n'; + pq.pop(); + } + } + else { // 선물을 충전하는 경우 + while (input--) { + cin >> gift; + pq.push(gift); + } + } + } + return 0; +} \ No newline at end of file diff --git "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\355\225\204\354\210\230/2075.cpp" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\355\225\204\354\210\230/2075.cpp" new file mode 100644 index 00000000..6779d50c --- /dev/null +++ "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\355\225\204\354\210\230/2075.cpp" @@ -0,0 +1,42 @@ +#include +#include + +using namespace std; + +/* +* HINT : 상위 n개의 숫자에서 n번째 숫자는 가장 작은 숫자네요! +*/ + +/* +* 입력되는 수 중 n번째로 큰 수를 찾자! +* -> 최종으로 상위 n개를 저장할 수 있는 구조 -> n개 이상일 때 가장 작은 값을 삭제할 수 있는 구조 +* -> 최소힙을 이용하자 +* -> 입력을 최소힙에 push하고 힙의 사이즈가 n보다 크다면 top값을 제거해주자 +* ->최종적으로 상위 n개의 숫자가 저장되고 top값이 n번째 큰 수가 된다! +*/ + +int main() { + + ios_base::sync_with_stdio(false); + cin.tie(0); + cout.tie(0); + + int n, num; + priority_queue, greater> pq; // 최소힙 + + // 입력 + cin >> n; + + // 연산 + for (int i = 0; i < n*n; i++) { + cin >> num; + pq.push(num); + if (pq.size() > n) {// 저장된 숫자의 개수가 n보다 많으면 가장 작은 값(top 값)을 제거 + pq.pop(); + } + } + + // 출력 + cout << pq.top(); + return 0; +} \ No newline at end of file diff --git "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\355\225\204\354\210\230/2607.cpp" "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\355\225\204\354\210\230/2607.cpp" new file mode 100644 index 00000000..d1907332 --- /dev/null +++ "b/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\355\225\204\354\210\230/2607.cpp" @@ -0,0 +1,70 @@ +#include +#include + +using namespace std; +const int NUM_CHARS = 26; + +/* +* 원본 단어와의 차이의 개수를 센다. +*/ + +/* + * [비슷한 단어] + * + * 단어가 같은 구성일 조건 + * 1. 두 개의 단어가 같은 종류의 문자로 이루어짐 + * 2. 같은 문자는 같은 개수만큼 있음 + * + * 비슷한 단어의 조건 + * 1. 한 단어에서 한 문자를 더하거나, 빼면 같은 구성이 됨 + * -> 두 단어에서 다른 문자의 개수가 총 1개 + * 2. 한 단어에서 한 문자를 바꾸면 같은 구성이 됨 + * -> 두 단어에서 다른 문자의 개수가 총 2개 + * -> !주의! 이때, 두 단어의 길이가 같아야 함 cf) doll | do + */ + +// 각 알파벳의 개수 세기 +void countFreq(string word, vector &freq) { + for (int i = 0; i < word.length(); i++) { + freq[word[i] - 'A']++; + } +} + +int countDiff(string word, vector original_freq) { + vector freq(NUM_CHARS, 0); + int diff = 0; // 원본 단어와의 차이 + + countFreq(word, freq); // 각 알파벳의 개수 세기 + + // 원본 단어와 다른 알파벳 개수 구하기 + for (int i = 0; i < NUM_CHARS; i++) { + diff += abs(original_freq[i] - freq[i]); + } + return diff; +} + +int main() { + int N, ans=0; + string original; + // 입력 + cin >> N; + cin >> original; + vector original_freq(NUM_CHARS, 0); + + // 연산 + countFreq(original, original_freq); + + for (int i = 1; i < N; i++) { + string word; + cin >> word; + + int diff = countDiff(word, original_freq); + // 비슷한 단어 세기 + if (diff == 0 || diff == 1 || diff == 2 && original.length() == word.length()) { + ans++; + } + } + // 출력 + cout << ans; + return 0; +} \ No newline at end of file diff --git "a/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\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/05_\354\232\260\354\204\240\354\210\234\354\234\204 \355\201\220/\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/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/README.md" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/README.md" index e69de29b..9d91dd26 100644 --- "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/README.md" +++ "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/README.md" @@ -0,0 +1,76 @@ +# 그리디 알고리즘 (Greedy Algorithm) + +[메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4) + +## 💻 튜터링 + +### 라이브 코딩 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :--------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :----------: | :----: | +| 11047 | 동전 0 | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/06_%EA%B7%B8%EB%A6%AC%EB%94%94%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/11047.cpp) | 그리디 | +| 1931 | 회의실 배정 | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/06_%EA%B7%B8%EB%A6%AC%EB%94%94%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/1931.cpp) | 그리디 | +| 프로그래머스 | 체육복 | **Lv.1** | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/06_%EA%B7%B8%EB%A6%AC%EB%94%94%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/%EC%B2%B4%EC%9C%A1%EB%B3%B5.cpp) | 그리디 | + +## ✏️ 과제 + +### 마감기한 + +~ 3 / 28 (화) 18:59 - 과제 제출
+~ 3 / 30 (목) 23:59 - 추가 제출
+ +### 필수 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------: | :-------: | :---------------: | +| 18111 | 마인크래프트 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/06_%EA%B7%B8%EB%A6%AC%EB%94%94%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/%ED%95%84%EC%88%98/18111.cpp) | 구현, 브루트 포스 | +| 1213 | 팰린드롬 만들기 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/06_%EA%B7%B8%EB%A6%AC%EB%94%94%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/%ED%95%84%EC%88%98/1213.cpp) | 그리디, 문자열 | +| 17451 | 평행 우주 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/06_%EA%B7%B8%EB%A6%AC%EB%94%94%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/%ED%95%84%EC%88%98/17451.cpp) | 그리디, 수학 | + +### 도전 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :--------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :----------: | +| 19539 | 사과나무 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/06_%EA%B7%B8%EB%A6%AC%EB%94%94%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/%EB%8F%84%EC%A0%84/19539.cpp) | 그리디, 수학 | +| 프로그래머스 | 큰 수 만들기 | **Lv.2** | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/06_%EA%B7%B8%EB%A6%AC%EB%94%94%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/%EB%8F%84%EC%A0%84/%ED%81%B0_%EC%88%98_%EB%A7%8C%EB%93%A4%EA%B8%B0.cpp) | 그리디 | + +--- + +### 힌트 + +
+마인크래프트 +
+    블록 높이의 최댓값을 살펴보아요. 입력의 크기가 작을 땐 어떻게 접근하면 좋을까요? +
+
+ +
+팰린드롬 만들기 +
+    팰린드롬이 존재하려면 어떤 조건을 만족해야 할까요? +
+
+ +
+평행 우주 +
+    자료형마다 값의 범위가 정해져 있다는걸 명심하세요. 어디에서부터 속도를 확인하는 게 더 유리할까요? +
+
+ +
+사과나무 +
+    골드라고 겁먹지 말아요:) 나무가 자라는 높이의 수학적인 성질을 이용하면 어렵지 않은 문제입니다! +
+
+ +
+큰 수 만들기 +
+    앞에 있는 숫자를 버리지 않고 뒤에 있는 숫자를 버리는 조건이 무엇일까요? +
+
+ +--- diff --git "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\352\260\225\354\235\230 \354\236\220\353\243\214/06_\352\267\270\353\246\254\353\224\224\354\225\214\352\263\240\353\246\254\354\246\230_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\352\260\225\354\235\230 \354\236\220\353\243\214/06_\352\267\270\353\246\254\353\224\224\354\225\214\352\263\240\353\246\254\354\246\230_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" new file mode 100644 index 00000000..3fa42bf0 Binary files /dev/null and "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\352\260\225\354\235\230 \354\236\220\353\243\214/06_\352\267\270\353\246\254\353\224\224\354\225\214\352\263\240\353\246\254\354\246\230_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" differ diff --git "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\352\260\225\354\235\230 \354\236\220\353\243\214/06_\352\267\270\353\246\254\353\224\224\354\225\214\352\263\240\353\246\254\354\246\230_\354\235\264\353\241\240.pdf" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\352\260\225\354\235\230 \354\236\220\353\243\214/06_\352\267\270\353\246\254\353\224\224\354\225\214\352\263\240\353\246\254\354\246\230_\354\235\264\353\241\240.pdf" new file mode 100644 index 00000000..5d290576 Binary files /dev/null and "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\352\260\225\354\235\230 \354\236\220\353\243\214/06_\352\267\270\353\246\254\353\224\224\354\225\214\352\263\240\353\246\254\354\246\230_\354\235\264\353\241\240.pdf" differ diff --git "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\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/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\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/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\217\204\354\240\204/19539.cpp" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\217\204\354\240\204/19539.cpp" new file mode 100644 index 00000000..5f214ab8 --- /dev/null +++ "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\217\204\354\240\204/19539.cpp" @@ -0,0 +1,50 @@ +#include +#include + +using namespace std; +/* +* 1. 한 번 물을 줄 때마다 3씩 나무가 자라므로, 나무 높이의 합(sum)은 3의 배수가 되어야 합니다. +* (이 때, 물을 주는 횟수 k는 `sum/3`이 됩니다.) +* 2. `홀수+홀수=짝수`, `짝수+짝수=짝수`, `홀수+홀수=짝수` 입니다. +* 따라서 k번 물을 준다면 홀수 높이는 최대 k개만 가능합니다. +*/ + +void summation(int &sum, int &height){ + sum += height; +} + +void countOdd(int &height, int &odd){ + if (height % 2) { //홀수 높이의 개수 세기 + odd++; + } +} + +bool solve(int sum, int odd) { + if (sum % 3) { //최종 나무 높이의 합이 3의 배수여야 함 + return false; + } + if (odd > sum / 3) { // (sum/3)은 물을 주는 횟수 + return false; + } + return true; +} +int main() { + int n, sum = 0, odd = 0; + + // 입력 + cin >> n; + + // 입력 & 연산 + for (int i = 0; i < n; i++) { + int height; + cin >> height; + summation(sum, height); + countOdd(height, odd); + } + + // 연산 & 출력 + solve(sum, odd) ? cout << "YES" : cout << "NO"; + //삼항연산자 + // `condition ? A : B` 형태 => condition이 참인 경우 A 실행(사용), condition이 거짓인 경우 B 실행(사용) + return 0; +} \ No newline at end of file diff --git "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\217\204\354\240\204/\355\201\260_\354\210\230_\353\247\214\353\223\244\352\270\260.cpp" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\217\204\354\240\204/\355\201\260_\354\210\230_\353\247\214\353\223\244\352\270\260.cpp" new file mode 100644 index 00000000..65799cb9 --- /dev/null +++ "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\217\204\354\240\204/\355\201\260_\354\210\230_\353\247\214\353\223\244\352\270\260.cpp" @@ -0,0 +1,32 @@ +#include +#include +/* +* 결론적으로 (문자열 길이 - k)개 만큼의 숫자를 합쳐 리턴해주면 된다. +* 즉, 앞에서부터 k, k+1, ... 번째 까지의 숫자들에 대해 최댓값을 하나씩 포함시키면 된다. +* 이 때, 이미 추가한 숫자가 있다면 그 뒤에 해당하는 숫자만을 추가해야 한다. +* (앞 숫자를 추가할 경우, 최댓값이 보장되지 않음) +*/ +using namespace std; + +string solution(string number, int k) { + string answer = ""; + int max_val = 0; + int max_idx = 0; + int idx = 0; + while (idx < number.length()) { + if (max_val < number[idx]) {//최댓값, 최댓값의 인덱스 갱신 + max_val = number[idx]; + max_idx = idx; + } + if (idx == k) { //k: 한 번 탐색하는 인덱스의 최댓값 + // k까지 다 탐색하면, 앞서 탐색한 숫자들 중 최댓값부터 다시 탐색을 시작한다 + // (앞부분을 추가하지 않기 위함) + idx = max_idx; + k++; //다음 탐색 범위 확대(k, k+1, ..., number.length() ) + answer.push_back(max_val); + max_val = 0; //새로운 최댓값을 찾아야 하므로 최댓값 초기화 + } + idx++; + } + return answer; +} diff --git "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\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/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\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/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11047.cpp" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11047.cpp" new file mode 100644 index 00000000..7f0532bc --- /dev/null +++ "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11047.cpp" @@ -0,0 +1,26 @@ +#include +#include + +using namespace std; +/* + * 큰 가치의 동전부터 사용하여 거슬러주면 되므로 그리디 알고리즘 이용 + * 동전 사용할 때마다 동전 개수와 남은 금액 갱신, 남은 금액 0 될 때까지 반복 + */ +int main() { + int n, k, cnt = 0; //cnt: count(필요한 동전 개수) + // 입력 + cin >> n >> k; + vector val(n); //동전 n종류의 값 입력받을 벡터 + for (int i = 0; i < n; i++) { + cin >> val[i]; + } + // 연산 + for (int i = n - 1; i >= 0; i--) { //큰 가치의 돈부터 사용 + cnt += k / val[i]; //동전 개수 갱신: 남은 금액/동전 가치 더하기 + k %= val[i]; //남은 금액 갱신: 동전 사용하고 남은 금액으로(나머지 연산자) + } + // 출력 + cout << cnt; + + return 0; +} diff --git "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/1931.cpp" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/1931.cpp" new file mode 100644 index 00000000..242bc59c --- /dev/null +++ "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/1931.cpp" @@ -0,0 +1,38 @@ +#include +#include +#include + +using namespace std; +/* + * 회의가 끝나는 시각이 빠른 회의부터 배정하면 되므로 그리디 알고리즘을 이용한다. + * 이 때, 마지막으로 진행한 회의가 끝난 시각보다 빠른 시각에 시작하는 회의는 배정이 불가능한 점을 고려해야 한다. + */ + +int main() { + ios_base::sync_with_stdio(0); + cin.tie(0), cout.tie(0); + // 입력 + int n; + cin >> n; + vector>v; + for (int i = 0; i < n; i++) { + int start, end; + cin >> start >> end; + v.push_back({ end,start }); //회의가 끝나는 시각을 기준으로 정렬할 것이므로 편의상 end부터 입력 + } + // 연산 + sort(v.begin(), v.end()); //끝나는 시각 기준 오름차순 정렬 + + int finish_conference = 0, answer = 0; + for (int i = 0; i < v.size(); i++) {//회의 끝나는 시각이 빠른 순서대로 배정 + if (v[i].second < finish_conference) { //회의 시작하는 시각이 기존 종료 시각보다 빠르다면 회의실 배정 불가 + continue; + } + finish_conference = v[i].first; //회의 종료 시각 갱신 + answer++; //배정 가능 회의 수 갱신 + } + // 출력 + cout << answer; + + return 0; +} \ No newline at end of file diff --git "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\354\262\264\354\234\241\353\263\265.cpp" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\354\262\264\354\234\241\353\263\265.cpp" new file mode 100644 index 00000000..f5d2f3f2 --- /dev/null +++ "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\354\262\264\354\234\241\353\263\265.cpp" @@ -0,0 +1,58 @@ +#include +#include +#include + +using namespace std; +/* + * 각 학생들이 가지고 있는 체육복의 개수를 배열에 저장 + * 1번 학생부터 양 옆의 학생으로부터 대여가 가능한지 여부를 확인하여 빌려준다. + * 최종적으로 체육복 개수가 1개 이상인 학생들의 인원을 센다. + */ + +int solution(int n, vector lost, vector reserve) { + int answer = 0; + + vector student(n + 1, 1); //체육복 개수 정보 담음 + + //입력내용대로 초기화 + for (int i = 0; i < reserve.size(); i++) { //여벌 체육복이 있는 학생은 플러스 + student[reserve[i]]++; + } + for (int i = 0; i < lost.size(); i++) { //체육복을 잃어버린 학생은 마이너스 + student[lost[i]]--; + } + + //1번부터 체육복 대여 가능 여부 체크 + for (int i = 1; i <= n; i++) { //1번 학생부터 체크하며 양옆으로 체육복을 빌릴 수 있는가 확인 + if (student[i] > 0) { //빌릴 필요가 없으면 넘어가기 + continue; + } + + if (student[i - 1] == 2) { //앞 번호 학생에게 여벌 체육복이 있는 경우 + student[i - 1]--; + student[i]++; + } + else if (student[i + 1] == 2) { //뒷 번호 학생에게 여벌 체육복이 있는 경우 + student[i] = student[i + 1] = 1; + } + } + + for (int i = 1; i <= n; i++) { //체육복을 입을 수 있는 학생 수 세기 + if (student[i] > 0) { + answer++; + } + } + + return answer; +} + +//프로그래머스 테스트용으로 실행 가능한 메인 함수 +int main() { + vector lost = {2, 4}; + vector reserve = {1, 3, 5}; + int n = 5; + + cout << solution(n, lost, reserve); + + return 0; +} diff --git "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\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/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\355\225\204\354\210\230/1213.cpp" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\355\225\204\354\210\230/1213.cpp" new file mode 100644 index 00000000..204c12db --- /dev/null +++ "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\355\225\204\354\210\230/1213.cpp" @@ -0,0 +1,62 @@ +#include +#include +#include + +using namespace std; + +/* +* A부터 순서대로 이용하면 알파벳순으로 가장 빠른 팰린드롬을 만들 수 있다 -> 그리디 알고리즘 +* 모든 알파벳이 짝수 개씩 존재하거나, 홀수 개 알파벳이 한 종류만 있는 경우에만 팰린드롬이 존재한다. +*/ +const int NUM_CHAR = 26; // 알파벳 총 개수: 26개 + +void pushString(string &str, int times, char ch) { + // str이라는 문자열의 뒤에 ch 문자를 times 횟수만큼 추가 + while (times--) { + str += ch; + } +} + +string isPalindrom(vector freq){ + string answer = ""; + int odd_index = -1; // 홀수 개수인 알파벳의 인덱스 체크 + // 팰린드롬 앞부분 만들기 & 가능한지 여부 체크 + for (int i = 0; i < NUM_CHAR; i++) { + if (freq[i] % 2 == 1) { + if (odd_index!=-1) { // 이미 홀수 개수인 알파벳이 존재한다면 팰린드롬 불가능 + return("I'm Sorry Hansoo"); + } + odd_index = i; // 홀수 개수인 알파벳이 처음이라면 인덱스 체크 + } + pushString(answer, freq[i] / 2, 'A' + i); + } + + // 홀수 개수 알파벳 존재한다면 가운데 문자 추가 + if (odd_index != -1) { + answer += 'A' + odd_index; + } + + // 팰린드롬 뒷부분 체크 + for (int i = NUM_CHAR-1; i >= 0; i--) { + pushString(answer, freq[i] / 2, 'A' + i); + } + + return answer; +} +int main() { + + // 입력 + string name; + cin >> name; + + vector freq(NUM_CHAR, 0); // 알파벳 26개마다 빈도수를 센다. 인덱스 0:'A', 1:'B', ... + + // 연산 + for (int i = 0; i < name.length(); i++) { + freq[name[i] - 'A']++; // 각 알파벳의 개수 세기 + } + + // 연산 & 출력 + cout << isPalindrom(freq); + return 0; +} \ No newline at end of file diff --git "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\355\225\204\354\210\230/17451.cpp" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\355\225\204\354\210\230/17451.cpp" new file mode 100644 index 00000000..c2b6b1a4 --- /dev/null +++ "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\355\225\204\354\210\230/17451.cpp" @@ -0,0 +1,32 @@ +#include +#include +#include + +using namespace std; + +/* +* 힌트: 자료형마다 값의 범위가 정해져 있다는걸 명심하세요. 어디에서부터 속도를 확인하는 게 더 유리할까요? +* +* 마지막 행성부터 시작하여, 출발속도가 현재 행성의 필요속도의 배수면서도 증가하도록 만든다. +*/ + +int main() { + int n; + vector planet; + // 입력 + cin >> n; + for (int i = 0; i < n; i++) { + double input; + cin >> input; + planet.push_back(input); + } + + // 연산 + double ans = 1; + for (int i = n - 1; i >= 0; i--) { + ans = ceil(ans / planet[i]) * planet[i]; + } + + // 출력 + cout << (long long)ans; +} \ No newline at end of file diff --git "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\355\225\204\354\210\230/18111.cpp" "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\355\225\204\354\210\230/18111.cpp" new file mode 100644 index 00000000..56b02a2c --- /dev/null +++ "b/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\355\225\204\354\210\230/18111.cpp" @@ -0,0 +1,83 @@ +#include +#include + +using namespace std; + +typedef pair pii; + +const int MAX_HEIGHT = 257; +const int INF = 987'654'321; + +// 모든 땅의 높이를 height로 만드는 비용 계산 +int calcCost(int height, int n, int m, int b, vector>& blocks) { + int cost = 0; + int added = 0; // 추가해야 하는 블록의 총 개수 + int removed = 0; // 제거해야 하는 블록의 총 개수 + + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + int gap = abs(height - blocks[i][j]); + + if (blocks[i][j] > height) { + // 목표 높이보다 높은 칸인 경우, gap개의 블록 제거 + removed += gap; + } + else if (blocks[i][j] < height) { + // 목표 높이보다 낮은 칸인 경우, gap개의 블록 추가 + added += gap; + } + } + } + + // 전체 비용 계산 + cost = 2 * removed + added; + + // 블록 개수가 부족하다면 모든 땅의 높이를 height로 만드는 것이 불가능 + return (added > (b + removed)) ? INF : cost; +} + +// 모든 땅의 높이를 같게 만드는 최소 비용과 그 때의 땅의 높이 +pii makeGroundEven(int n, int m, int b, vector>& ground) { + int minCost = INF; + int height = 0; + + // 모든 높이를 다 만들어보고 최소 비용 찾기 + for (int i = 0; i < MAX_HEIGHT; i++) { + int cost = calcCost(i, n, m, b, ground); + if (cost <= minCost) { + minCost = cost; + height = i; + } + } + + return {minCost, height}; +} + +/** + * 블록 높이의 최댓값이 256밖에 되지 않으므로 + * 모든 칸을 높이 n(0~256)으로 만드는 모든 경우를 시도해보고 + * 그 중에서 비용이 최소가 될 때를 찾는다. + * + * 모든 칸을 높이 n으로 만드는 + */ + +int main() { + int n, m, b; + + // 입력 + cin >> n >> m >> b; + vector> ground(n, vector(m)); + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + cin >> ground[i][j]; + } + } + + // 연산 + pii answer = makeGroundEven(n, m, b, ground); + + // 출력 + cout << answer.first << " " << answer.second << "\n"; + + return 0; +} \ No newline at end of file diff --git "a/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\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/06_\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\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/07_DFS & BFS/README.md b/07_DFS & BFS/README.md new file mode 100644 index 00000000..2e70e8df --- /dev/null +++ b/07_DFS & BFS/README.md @@ -0,0 +1,76 @@ +# DFS & BFS + +[메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4) + +## 💻 튜터링 + +### 라이브 코딩 + +|문제 번호|문제 이름|난이도|풀이 링크|분류| +| :-----: | :-----: | :-----: | :-----: | :-----: | +|1260|DFS와 BFS||[C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/1260.cpp)|DFS, BFS| +|2606|바이러스||[C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/2606.cpp)|DFS, BFS| +|7576|토마토||[C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/7576.cpp)|BFS| + +## ✏️ 과제 + +### 마감기한 + +~ 4 / 4 (화) 18:59 - 과제 제출
+~ 4 / 6 (목) 23:59 - 추가 제출
+ +### 필수 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :---------------------------------------------------------------------: | :------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :---------------: | +| 2615 | 오목 | | [C++_v1](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%ED%95%84%EC%88%98/2615_v1.cpp)
[C++_v2](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%ED%95%84%EC%88%98/2615_v2.cpp) | 구현, 브루트 포스 | +| 4963 | 섬의 개수 | | [C++_v1](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%ED%95%84%EC%88%98/4963_v1.cpp)
[C++_v2](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%ED%95%84%EC%88%98/4963_v2.cpp) | DFS, BFS | +| 1325 | 효율적인 해킹 | | [C++_v1](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%ED%95%84%EC%88%98/1325_v1.cpp)
[C++_v2](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%ED%95%84%EC%88%98/1325_v2.cpp) | DFS, BFS | + +### 도전 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :--: | +| 프로그래머스 | 게임 맵 최단거리 | **Lv.2** | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%EB%8F%84%EC%A0%84/%EA%B2%8C%EC%9E%84_%EB%A7%B5_%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC.cpp) | BFS | +| 19538 | 루머 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%EB%8F%84%EC%A0%84/19538.cpp) | BFS | + +--- + +### 힌트 + +
+오목 +
+    여섯 알 이상이 연속이면 오목으로 인정하지 않고, 딱 다섯 알이 연속인 경우에는 가장 왼쪽 위에 있는 돌을 출력한다는 조건을 잘 기억해주세요! 이 조건을 잘 응용해보면 탐색 방향도 정해볼 수 있겠네요. +
+
+ +
+섬의 개수 +
+    탐색을 한 번 하면 하나의 영역을 구할 수 있어요! +
+
+ +
+효율적인 해킹 +
+    a가 b를 신뢰할 때, b를 해킹하면 a도 해킹할 수 있어요. 인접 리스트를 이용해서 단방향 그래프를 구현해볼까요? +
+
+ +
+게임 맵 최단거리 +
+    최단거리를 구하는 문제네요. BFS를 사용해볼까요? +
+
+ +
+루머 +
+    주변인의 절반 이상이 루머를 믿을 때 본인도 루머를 믿어요! 루머를 믿는 사람은 자신의 주변인에게 루머를 "동시에" 퍼뜨리고 있다는 것을 주의해주세요. +
+
+ +--- diff --git "a/07_DFS & BFS/\352\260\225\354\235\230 \354\236\220\353\243\214/07_DFS&BFS_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" "b/07_DFS & BFS/\352\260\225\354\235\230 \354\236\220\353\243\214/07_DFS&BFS_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" new file mode 100644 index 00000000..435236ba Binary files /dev/null and "b/07_DFS & BFS/\352\260\225\354\235\230 \354\236\220\353\243\214/07_DFS&BFS_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" differ diff --git "a/07_DFS & BFS/\352\260\225\354\235\230 \354\236\220\353\243\214/07_DFS&BFS_\354\235\264\353\241\240.pdf" "b/07_DFS & BFS/\352\260\225\354\235\230 \354\236\220\353\243\214/07_DFS&BFS_\354\235\264\353\241\240.pdf" new file mode 100644 index 00000000..11602688 Binary files /dev/null and "b/07_DFS & BFS/\352\260\225\354\235\230 \354\236\220\353\243\214/07_DFS&BFS_\354\235\264\353\241\240.pdf" differ diff --git "a/07_DFS & BFS/\353\217\204\354\240\204/19538.cpp" "b/07_DFS & BFS/\353\217\204\354\240\204/19538.cpp" new file mode 100644 index 00000000..38abce2d --- /dev/null +++ "b/07_DFS & BFS/\353\217\204\354\240\204/19538.cpp" @@ -0,0 +1,83 @@ +#include +#include +#include +#include + +using namespace std; + +const int NOT_BELIEVE = -1; + +vector bfs(int n, vector> &adj_list, vector &spreader) { + vector result(n+1, NOT_BELIEVE); // 루머 믿기 시작한 시간 + vector adj_believer_cnt(n+1, 0); // 루머를 믿는 주변인의 수 + queue q; + + for(int i = 0; i < spreader.size(); i++) { // 루머 유포자 세팅 + int p = spreader[i]; // 루머 유포자 p + result[p] = 0; // (== 루머 유포자는 처음부터 루머를 믿고 있기 때문에 0초 세팅) + q.push(p); + } + + while(!q.empty()) { + int node = q.front(); // 루머를 믿는 node + int w = result[node]; // node가 루머를 믿기 시작한 시간 + q.pop(); + + for(int i = 0; i < adj_list[node].size(); i++) { + /* + * node가 주변인 next_node에게 루머를 유포하고자 한다. + * node가 루머를 믿고 있으므로 루머를 믿는 next_node의 주변인의 수가 증가한다. + */ + int next_node = adj_list[node][i]; + adj_believer_cnt[next_node]++; // (== next_node의 주변인 node가 루머를 믿는다) + + /* + * [next_node가 루머를 믿기 시작하는 경우] + * 1. 아직 루머를 믿고 있지 않으며 + * 2. next_node의 주변인의 절반 이상이 루머를 믿고 있다. + */ + if(result[next_node] == NOT_BELIEVE && adj_believer_cnt[next_node] >= ceil((float) adj_list[next_node].size() / 2)) { + result[next_node] = w+1; + q.push(next_node); + } + } + } + return result; +} + +/* + * [루머 유포하기] + * 전제조건 : "주변인의 절반 이상이 루머를 믿을 때 본인도 루머를 믿는다." + * -> 루머를 믿는 주변인의 수를 계산해야 한다. +*/ + +int main() { + int n, m, p; + vector> adj_list; + vector spreader; // 루머 유포자 번호 저장 + + // 입력 + cin >> n; + adj_list.assign(n+1, vector (0)); + for(int i = 1; i <= n; i++) { // i사람 주변인 입력 + while(true) { + cin >> p; + if(p == 0) { + break; + } + adj_list[i].push_back(p); + } + } + cin >> m; + spreader.assign(m, 0); + for(int i = 0; i < m; i++) { + cin >> spreader[i]; + } + + // 연산 & 출력 + vector result = bfs(n, adj_list, spreader); + for(int i = 1; i <= n; i++) { + cout << result[i] << ' '; + } + return 0; +} \ No newline at end of file diff --git "a/07_DFS & BFS/\353\217\204\354\240\204/\352\262\214\354\236\204_\353\247\265_\354\265\234\353\213\250\352\261\260\353\246\254.cpp" "b/07_DFS & BFS/\353\217\204\354\240\204/\352\262\214\354\236\204_\353\247\265_\354\265\234\353\213\250\352\261\260\353\246\254.cpp" new file mode 100644 index 00000000..829f049d --- /dev/null +++ "b/07_DFS & BFS/\353\217\204\354\240\204/\352\262\214\354\236\204_\353\247\265_\354\265\234\353\213\250\352\261\260\353\246\254.cpp" @@ -0,0 +1,62 @@ +#include +#include +#include + +using namespace std; + +typedef pair pi; +int dr[4] = {-1, 1, 0, 0}; +int dc[4] = {0, 0, -1, 1}; + +const int NOT_VISITED = -1; + +int bfs(vector> &maps) { // 상대 팀 진영에 도착하기 이해 지나가야 하는 칸의 수 반환 + int n = maps.size(), m = maps[0].size(); + vector> w(n, vector (m, NOT_VISITED)); // 해당 칸까지 가기 위해 지나가야 하는 칸 수 + queue q; + + // 시작점 push + q.push({0, 0}); + w[0][0] = 1; + + while(!q.empty()) { + int r = q.front().first; + int c = q.front().second; + if(r == n-1 && c == m-1) { // 상대팀 진영에 도착한 경우 + return w[n-1][m-1]; + } + int weight = w[r][c]; // (r,c)까지 이동하는데 지나간 칸의 수 + q.pop(); + + for(int i = 0; i < 4; i++) { + int nr = r + dr[i]; + int nc = c + dc[i]; + + // 다음 칸으로 이동할 수 있는 경우 (== 벽이 아니고 방문한 적이 없는 칸인 경우) + if(nr >= 0 && nr < n && nc >= 0 && nc < m && maps[nr][nc] && w[nr][nc] == NOT_VISITED) { + q.push({nr, nc}); + w[nr][nc] = weight+1; + } + } + } + return w[n-1][m-1]; +} + +int solution(vector > maps) +{ + return bfs(maps); +} + +/* + * 상대 팀 진영에 도착하기 위해 지나가야 하는 칸의 개수 구하기 + * == 최단 거리 구하기 + * -> bfs를 이용한다! +*/ + +int main() { + vector> maps = {{1,0,1,1,1},{1,0,1,0,1},{1,0,1,1,1},{1,1,1,0,1},{0,0,0,0,1}}; + + // 연산 & 출력 + cout << solution(maps); + return 0; +} \ No newline at end of file diff --git "a/07_DFS & BFS/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/1260.cpp" "b/07_DFS & BFS/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/1260.cpp" new file mode 100644 index 00000000..d7f8e297 --- /dev/null +++ "b/07_DFS & BFS/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/1260.cpp" @@ -0,0 +1,101 @@ +#include +#include +#include +#include + +using namespace std; + +vector visited_recur; + +vector dfs(int n, int v, vector> &edge) { + vector result; + vector visited (n+1, false); + stack s; + + s.push(v); + visited[v] = true; + result.push_back(v); + + while(!s.empty()) { + int node = s.top(); + bool child = false; + + for(int i = 1; i <= n; i++) { + if(edge[node][i] && !visited[i]) { + child = true; + s.push(i); + visited[i] = true; + result.push_back(i); + break; + } + } + if(!child) { + s.pop(); + } + } + return result; +} + +void dfsRecur(int n, int node, vector> &edge) { + visited_recur[node] = true; + cout << node << ' '; + + for(int i = 1; i <= n; i++) { + if(edge[node][i] && !visited_recur[i]) { + dfsRecur(n, i, edge); + } + } +} + +vector bfs(int n, int v, vector> &edge) { + vector result; + vector visited (n+1, false); + queue q; + + q.push(v); + visited[v] = true; + + while(!q.empty()) { + int node = q.front(); + q.pop(); + result.push_back(node); + + for(int i = 1; i <= n; i++) { + if(edge[node][i] && !visited[i]) { + q.push(i); + visited[i] = true; + } + } + } + return result; +} + +int main() { + int n, m, v, n1, n2; + vector> edge; + + // 입력 + cin >> n >> m >> v; + edge.assign(n+1, vector (n+1, false)); + visited_recur.assign(n+1, false); + while(m--) { + cin >> n1 >> n2; + edge[n1][n2] = true; + edge[n2][n1] = true; + } + + // 연산 + vector dfs_result = dfs(n, v, edge); + vector bfs_result = bfs(n, v, edge); + + // 출력 + for(int i = 0; i < dfs_result.size(); i++) { + cout << dfs_result[i] << ' '; + } + cout << '\n'; + //dfsRecur(n, v, edge); + for(int i = 0; i < bfs_result.size(); i++) { + cout << bfs_result[i] << ' '; + } + return 0; +} \ No newline at end of file diff --git "a/07_DFS & BFS/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2606.cpp" "b/07_DFS & BFS/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2606.cpp" new file mode 100644 index 00000000..99f76b09 --- /dev/null +++ "b/07_DFS & BFS/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2606.cpp" @@ -0,0 +1,69 @@ +#include +#include +#include + +using namespace std; + +vector visited_dfs; + +void dfs(int node, vector> &graph) { + visited_dfs[node] = true; + + for(int i = 0; i < graph[node].size(); i++) { + int next_node = graph[node][i]; + if(!visited_dfs[next_node]) { + dfs(next_node, graph); + } + } +} + +int bfs(int n, vector> &graph) { + int cnt = 0; + vector visited (n+1, false); + queue q; + + q.push(1); + visited[1] = true; + + while(!q.empty()) { + int node = q.front(); + q.pop(); + + for(int i = 0; i < graph[node].size(); i++) { + int next_node = graph[node][i]; + if(!visited[next_node]) { + q.push(next_node); + visited[next_node] = true; + cnt++; + } + } + } + return cnt; +} + +int main() { + int n, m, n1, n2; + vector> graph; + + // 입력 + cin >> n >> m; + graph.assign(n+1, vector (0)); + //visited_dfs.assign(n+1, false); + while(m--) { + cin >> n1 >> n2; + graph[n1].push_back(n2); + graph[n2].push_back(n1); + } + + // 연산 & 출력 + cout << bfs(n, graph); + /*dfs(1, graph); + int cnt = 0; + for(int i = 2; i <= n; i++) { + if(visited_dfs[i]) { + cnt++; + } + } + cout << cnt;*/ + return 0; +} \ No newline at end of file diff --git "a/07_DFS & BFS/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/7576.cpp" "b/07_DFS & BFS/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/7576.cpp" new file mode 100644 index 00000000..d698b6d9 --- /dev/null +++ "b/07_DFS & BFS/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/7576.cpp" @@ -0,0 +1,66 @@ +#include +#include +#include + +using namespace std; + +typedef pair pi; + +int bfs(int n, int m, int raw, queue &q, vector> &box) { + int w; + int dr[4] = {-1, 1, 0, 0}; + int dc[4] = {0, 0, -1, 1}; + + while(!q.empty()) { + int r = q.front().first; + int c = q.front().second; + w = box[r][c]; + q.pop(); + + for(int i = 0; i < 4; i++) { + int nr = r + dr[i]; + int nc = c + dc[i]; + + if(nr >= 0 && nr < n && nc >= 0 && nc < m && box[nr][nc] == 0) { + q.push({nr, nc}); + box[nr][nc] = w + 1; + raw--; + } + } + } + + if(raw == 0) { + return w-1; + } + return -1; +} + +int main() { + int n, m, raw = 0; + vector> box; + queue q; + + // 입력 + cin >> m >> n; + box.assign(n, vector (m, 0)); + for(int i = 0; i < n; i++) { + for(int j = 0; j < m; j++) { + cin >> box[i][j]; + if(box[i][j] == 1) { + q.push({i, j}); + } + else if(box[i][j] == 0){ + raw++; + } + } + } + + // 연산 & 출력 + if(raw == 0) { + cout << 0; + } + else { + cout << bfs(n, m, raw, q, box); + } + return 0; +} \ No newline at end of file diff --git "a/07_DFS & BFS/\355\225\204\354\210\230/1325_v1.cpp" "b/07_DFS & BFS/\355\225\204\354\210\230/1325_v1.cpp" new file mode 100644 index 00000000..5ca9cc32 --- /dev/null +++ "b/07_DFS & BFS/\355\225\204\354\210\230/1325_v1.cpp" @@ -0,0 +1,68 @@ +#include +#include +#include + +using namespace std; + +vector hacked; // 컴퓨터 해킹 여부 저장 + +int dfs(int node, vector> &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 hack(int n, vector> &graph) { // 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터 번호 반환 + int max_cnt = 0; // 감염된 컴퓨터 수의 최댓값 + vector 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> graph; + + // 입력 + cin >> n >> m; + graph.assign(n+1, vector (0)); + while(m--) { + /* + * a는 b를 신뢰한다 + * == b는 a를 감염시킬 수 있다 + */ + cin >> a >> b; + graph[b].push_back(a); + } + + // 연산 & 출력 + vector result = hack(n, graph); + for(int i = 0; i < result.size(); i++) { + cout << result[i] << ' '; + } + return 0; +} diff --git "a/07_DFS & BFS/\355\225\204\354\210\230/1325_v2.cpp" "b/07_DFS & BFS/\355\225\204\354\210\230/1325_v2.cpp" new file mode 100644 index 00000000..a22a1e63 --- /dev/null +++ "b/07_DFS & BFS/\355\225\204\354\210\230/1325_v2.cpp" @@ -0,0 +1,76 @@ +#include +#include +#include + +using namespace std; + +int bfs(int s, int n, vector> &graph) { // s번 컴퓨터가 해킹할 수 있는 컴퓨터 개수 세기 + int cnt = 1; // s가 해킹할 수 있는 컴퓨터 수 + vector hacked (n+1, false); // 컴퓨터 해킹 여부 저장 + queue q; + + hacked[s] = true; + q.push(s); + + while(!q.empty()) { + int node = q.front(); + q.pop(); + + for(int i = 0; i < graph[node].size(); i++) { // node 컴퓨터가 해킹할 수 있는 컴퓨터 탐색 + int next_node = graph[node][i]; + if(!hacked[next_node]) { // 아직 해킹되지 않은 컴퓨터 발견 + cnt++; + hacked[next_node] = true; + q.push(next_node); + } + } + } + return cnt; +} + +vector hack(int n, vector> &graph) { // 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터 번호 반환 + int max_cnt = 0; // 감염된 컴퓨터 수의 최댓값 + vector result; // 컴퓨터 번호 저장 + + for(int i = 1; i <= n; i++) { // i : 최초로 해킹된 컴퓨터 + int tmp = bfs(i, n, 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> graph; + + // 입력 + cin >> n >> m; + graph.assign(n+1, vector (0)); + while(m--) { + /* + * a는 b를 신뢰한다 + * == b는 a를 감염시킬 수 있다 + */ + cin >> a >> b; + graph[b].push_back(a); + } + + // 연산 & 출력 + vector result = hack(n, graph); + for(int i = 0; i < result.size(); i++) { + cout << result[i] << ' '; + } + return 0; +} \ No newline at end of file diff --git "a/07_DFS & BFS/\355\225\204\354\210\230/2615_v1.cpp" "b/07_DFS & BFS/\355\225\204\354\210\230/2615_v1.cpp" new file mode 100644 index 00000000..3c673212 --- /dev/null +++ "b/07_DFS & BFS/\355\225\204\354\210\230/2615_v1.cpp" @@ -0,0 +1,99 @@ +#include +#include + +using namespace std; + +const int MAX_LEN = 19; +typedef pair ci; + +int dx[4] = {0, 1, 1, -1}; +int dy[4] = {1, 0, 1, 1}; + +bool isValid(vector> &arr, ci s) { + int cnt, x, y, nx, ny; + // 시작점 좌표 설정 + x = s.first; + y = s.second; + + // 4가지 방향으로 탐색 + for (int i = 0; i < 4; i++) { + nx = x; + ny = y; + for (cnt = 0; cnt < 5; cnt++) { + nx += dx[i]; + ny += dy[i]; + // 현재 탐색하는 돌이 같은 색 돌이면 -> 반복문 반복 + if ((0 < nx && nx <= MAX_LEN && 0 < ny && ny <= MAX_LEN) && arr[nx][ny] == arr[x][y]) { + continue; + } + // 그렇지 않으면 -> break + break; + } + if (cnt == 4) { // 탐색한 방향으로 다섯 알이 연속인 경우 + // 역방향 좌표 + nx = x - dx[i]; + ny = y - dy[i]; + // 역방향에는 돌을 놓을 수 없을 때 -> 오목 O + if (!(0 < nx && nx <= MAX_LEN && 0 < ny && ny <= MAX_LEN)) { + return true; + } + // 역방향에 같은 색 돌이 없을 때 -> 오목 O + else if (arr[nx][ny] != arr[x][y]) { + return true; + } + // 역방향에 같은 색 돌이 있을 때 -> 오목 x + } + } + return false; +} +/** 해당 색의 돌이 게임을 이기면 가장 왼쪽 위에 있는 바둑알의 위치를, {0, 0} 리턴 */ +ci solution(vector> &arr, vector &stones) { + for (auto s : stones) { + if (isValid(arr, s)) { // s를 시작점으로 오목이 가능하다면 + return s; // s 반환 + } + } + //{0, 0} 반환 + return {0, 0}; +} +/**[백준 2615: 오목] + * (주의) + * - 게임에서 이기면 연속된 다섯 개의 가장 왼쪽 위에 있는 바둑알을 출력해야 하므로 탐색 방향에 유의 + * - 여섯 알 이상이 연속이면 오목 X + * 1. 바둑판의 상태를 입력받아 검은색 돌의 위치와 흰색 돌의 위치를 각각 저장 + * 2. 각각의 돌을 시작점으로 하여 오목을 만들 수 있는지 판단 + * 3. 최대 4개의 돌이 연속하거나, 5개의 돌이 연속했지만 탐색한 반대 방향에도 같은 색의 돌이 있으면 오목 실패 + * 4. 오목에 성공했으면 시작점으로 한 돌의 좌표 반환 + * 실패했으면 {0, 0} 반환 +*/ +int main() { + // 입력 + vector> arr(MAX_LEN + 1, vector(MAX_LEN + 1)); + vector black_stones, white_stones; + for (int i = 1; i <= MAX_LEN; i++) { + for (int j = 1; j <= MAX_LEN; j++) { + cin >> arr[i][j]; + if (arr[i][j] == 1) { + black_stones.push_back({i, j}); + } else if (arr[i][j] == 2) { + white_stones.push_back({i, j}); + } + } + } + + // 연산 + ci black_win = solution(arr, black_stones); + ci white_win = solution(arr, white_stones); + + // 출력 + if (black_win.first) { // 검은 돌 승리 + cout << "1\n" + << black_win.first << " " << black_win.second; + } else if (white_win.first) { // 흰 돌 승리 + cout << "2\n" + << white_win.first << " " << white_win.second; + } else { + cout << "0"; + } + return 0; +} \ No newline at end of file diff --git "a/07_DFS & BFS/\355\225\204\354\210\230/2615_v2.cpp" "b/07_DFS & BFS/\355\225\204\354\210\230/2615_v2.cpp" new file mode 100644 index 00000000..ab5f48cc --- /dev/null +++ "b/07_DFS & BFS/\355\225\204\354\210\230/2615_v2.cpp" @@ -0,0 +1,69 @@ +#include + +using namespace std; + +const int SIZE = 19; + +int winner = 0, row, col; +int board[SIZE+1][SIZE+1]; // 오목판 +/* + * 방향은 우향, 하향, 우상향, 우하향만 고려한다. + * 왼쪽에서 오른쪽으로, 위에서 아래로 탐색하기 때문에 나머지 방향들은 사전에 발견할 수 있기 때문이다. +*/ +int dr[4] = {0, 1, -1, 1}, dc[4] = {1, 0, 1, 1}; + +bool isFirstTravel(int r, int c, int dir, int color) { // 이전에 탐색된 방향인가 (반대방향에 해당 색상의 돌이 있었는가) + int br = r - dr[dir]; + int bc = c - dc[dir]; + if(br >= 1 && br <= SIZE && bc >= 1 && bc <= SIZE && board[br][bc] == color) { + return false; + } + return true; +} + +int dfs(int r, int c, int dir, int color) { + int cnt = 1; + int nr = r + dr[dir]; + int nc = c + dc[dir]; + if(nr >= 1 && nr <= SIZE && nc >= 1 && nc <= SIZE && board[nr][nc] == color) { + cnt += dfs(nr, nc, dir, color); + } + return cnt; +} + +void game() { + for(int j = 1; j <= SIZE; j++) { + for(int i = 1; i <= SIZE; i++) { + if(board[i][j] == 0) { // 빈칸 PASS + continue; + } + for(int k = 0; k < 4; k++) { // 방향별 탐색 시작 + if(!isFirstTravel(i, j, k, board[i][j])) { // 이전에 탐색한 경우 PASS + continue; + } + if(dfs(i, j, k, board[i][j]) == 5) { // 이기는 경우 발견 + winner = board[i][j]; + row = i; + col = j; + return; + } + } + } + } +} + +int main() { + // 입력 + for(int i = 1; i <= SIZE; i++) { + for(int j = 1; j <= SIZE; j++) { + cin >> board[i][j]; + } + } + + game(); + cout << winner << '\n'; + if(winner) { + cout << row << ' ' << col; + } + return 0; +} \ No newline at end of file diff --git "a/07_DFS & BFS/\355\225\204\354\210\230/4963_v1.cpp" "b/07_DFS & BFS/\355\225\204\354\210\230/4963_v1.cpp" new file mode 100644 index 00000000..5720ed79 --- /dev/null +++ "b/07_DFS & BFS/\355\225\204\354\210\230/4963_v1.cpp" @@ -0,0 +1,63 @@ +#include +#include + +using namespace std; + +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 dfs(int sr, int sc, int h, int w, vector> &map) { // dfs 탐색 + map[sr][sc] = VISITED; // 방문 check + + for(int i = 0; i < 8; i++) { // 이어진 땅 없는지 탐색 + int nr = sr + dr[i]; + int nc = sc + dc[i]; + + if(nr >= 0 && nr < h && nc >= 0 && nc < w && map[nr][nc] == 1) { // 땅 발견 + dfs(nr, nc, h, w, map); + } + } +} + +int cntIsland(int h, int w, vector> &map) { // 섬 개수 세기 + int cnt = 0; + for(int i = 0; i < h; i++) { + for(int j = 0; j < w; j++) { + if(map[i][j] == 1) { // 땅 발견 + cnt++; + dfs(i, j, h, w, map); // (i,j)와 연결된 땅 탐색 (== 섬 만들기) + } + } + } + return cnt; +} + +/* + * [섬의 개수 세기] + * 1. 땅을 발견할 때마다 그래프 탐색을 이용하여 연결된 땅을 찾아 섬을 만든다. + * 2. 따라서 그래프 탐색 횟수가 섬의 개수가 된다. +*/ + +int main() { + int w, h; + vector> map; + + while(true) { + // 입력 + cin >> w >> h; + if(w == 0 && h == 0) { // 종료조건 + break; + } + map.assign(h, vector (w, 0)); + 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; +} \ No newline at end of file diff --git "a/07_DFS & BFS/\355\225\204\354\210\230/4963_v2.cpp" "b/07_DFS & BFS/\355\225\204\354\210\230/4963_v2.cpp" new file mode 100644 index 00000000..cbcdd7c0 --- /dev/null +++ "b/07_DFS & BFS/\355\225\204\354\210\230/4963_v2.cpp" @@ -0,0 +1,77 @@ +#include +#include +#include + +using namespace std; + +typedef pair 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> &map) { // bfs 탐색 + queue 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> &map) { // 섬 개수 세기 + int cnt = 0; + for(int i = 0; i < h; i++) { + for(int j = 0; j < w; j++) { + if(map[i][j] == 1) { // 땅 발견 + cnt++; + bfs(i, j, h, w, map); // (i,j)와 연결된 땅 탐색 (== 섬 만들기) + } + } + } + return cnt; +} + +/* + * [섬의 개수 세기] + * 1. 땅을 발견할 때마다 그래프 탐색을 이용하여 연결된 땅을 찾아 섬을 만든다. + * 2. 따라서 그래프 탐색 횟수가 섬의 개수가 된다. +*/ + +int main() { + int w, h; + vector> map; + + while(true) { + // 입력 + cin >> w >> h; + if(w == 0 && h == 0) { // 종료조건 + break; + } + + map.assign(h, vector (w, 0)); + 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; +} \ No newline at end of file diff --git "a/07_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/README.md" "b/07_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/README.md" deleted file mode 100644 index e69de29b..00000000 diff --git "a/07_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\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/07_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\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/07_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\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/07_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\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/07_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" "b/07_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\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/07_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\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/07_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\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/08_DFS & BFS/README.md b/08_DFS & BFS/README.md deleted file mode 100644 index e69de29b..00000000 diff --git "a/08_DFS & BFS/\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/08_DFS & BFS/\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/08_DFS & BFS/\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/08_DFS & BFS/\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/08_DFS & BFS/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" "b/08_DFS & BFS/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\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/08_DFS & BFS/\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/08_DFS & BFS/\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/08_\353\260\261\355\212\270\353\236\230\355\202\271/README.md" "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/README.md" new file mode 100644 index 00000000..f998fafc --- /dev/null +++ "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/README.md" @@ -0,0 +1,75 @@ +# 백트래킹 + +[메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4) + +## 💻 튜터링 + +### 라이브 코딩 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :---------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :----------: | :------: | +| 15649 | N과 M (1) | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/08_%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/15649.cpp) | 백트래킹 | +| 9663 | N-Queen | | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/08_%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/9663.cpp) | 백트래킹 | + +## ✏️ 과제 + +### 마감기한 + +~ 5 / 1 (월) 23:59 - 과제 제출
+~ 5 / 4 (목) 23:59 - 추가 제출
+ +### 필수 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :--------------: | +| 20055 | 컨베이어 벨트 위의 로봇 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/08_%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9/%ED%95%84%EC%88%98/20055.cpp) | 구현, 시뮬레이션 | +| 14888 | 연산자 끼워넣기 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/08_%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9/%ED%95%84%EC%88%98/14888.cpp) | 백트래킹 | +| 14889 | 스타트와 링크 | | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/08_%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9/%ED%95%84%EC%88%98/14889.cpp) | 백트래킹 | + +### 도전 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :--------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :------: | +| 프로그래머스 | 소수 찾기 | **Lv.2** | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/08_%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9/%EB%8F%84%EC%A0%84/%EC%86%8C%EC%88%98_%EC%B0%BE%EA%B8%B0.cpp) | 백트래킹 | +| 2580 | 스도쿠 | | [C++_v1](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/08_%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9/%EB%8F%84%EC%A0%84/2580_v1.cpp)
[C++_v2](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/08_%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9/%EB%8F%84%EC%A0%84/2580_v2.cpp) | 백트래킹 | + +--- + +### 힌트 + +
+컨베이어 벨트 위의 로봇 +
+    회전에 적합한 자료구조를 사용해볼까요? 로봇이 내리는 위치에 도달하면 반드시 내린다는 것을 잊지 마세요! +
+
+ +
+연산자 끼워넣기 +
+    수열의 길이와 연산자의 개수가 매우 적네요! 연산자의 가능한 배치를 모두 구해볼까요? +
+
+ +
+스타트와 링크 +
+    팀을 나누기만 한다면 계산은 쉬워 보여요. 우선 한 팀에 배치하는 경우로 생각해 볼까요? +
+
+ +
+소수 찾기 +
+    결국 순열을 만드는 문제네요. 대신 순열 길이에 제한이 없어요! 모든 길이의 순열을 다 구하려면 어떻게 해야 할까요? +
+
+ +
+스도쿠 +
+    아주 익숙한 스도쿠입니다! 스도쿠 문제를 풀 때 어떻게 했었나요? 일단 가능한 숫자를 넣어보고 안되면 다른 숫자를 넣어봐요! 그나저나 같은 구역인지는 어떻게 알까요? 같은 구역의 크기는 3 x 3 이네요! N-queen 문제와 비슷하게 접근해볼까요? +
+
+ +--- diff --git "a/08_\353\260\261\355\212\270\353\236\230\355\202\271/\352\260\225\354\235\230 \354\236\220\353\243\214/08_\353\260\261\355\212\270\353\236\230\355\202\271_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\352\260\225\354\235\230 \354\236\220\353\243\214/08_\353\260\261\355\212\270\353\236\230\355\202\271_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" new file mode 100644 index 00000000..f09b27f6 Binary files /dev/null and "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\352\260\225\354\235\230 \354\236\220\353\243\214/08_\353\260\261\355\212\270\353\236\230\355\202\271_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" differ diff --git "a/08_\353\260\261\355\212\270\353\236\230\355\202\271/\352\260\225\354\235\230 \354\236\220\353\243\214/08_\353\260\261\355\212\270\353\236\230\355\202\271_\354\235\264\353\241\240.pdf" "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\352\260\225\354\235\230 \354\236\220\353\243\214/08_\353\260\261\355\212\270\353\236\230\355\202\271_\354\235\264\353\241\240.pdf" new file mode 100644 index 00000000..2b8e7dbc Binary files /dev/null and "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\352\260\225\354\235\230 \354\236\220\353\243\214/08_\353\260\261\355\212\270\353\236\230\355\202\271_\354\235\264\353\241\240.pdf" differ diff --git "a/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\217\204\354\240\204/2580_v1.cpp" "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\217\204\354\240\204/2580_v1.cpp" new file mode 100644 index 00000000..3c7db3bc --- /dev/null +++ "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\217\204\354\240\204/2580_v1.cpp" @@ -0,0 +1,119 @@ +#include +#include + +using namespace std; + +const int MAX = 9; + +bool is_finished; +int sudoku[MAX][MAX]; + +bool checkRow(int r, int n) { + for (int i = 0; i < MAX; i++) { + if (sudoku[r][i] == n) { + return false; + } + } + + return true; +} + +bool checkCol(int c, int n) { + for (int i = 0; i < MAX; i++) { + if (sudoku[i][c] == n) { + return false; + } + } + + return true; +} + +bool checkSquare(int r, int c, int n) { + // (base_r, base_c): (r,c)가 속한 정사각형의 왼쪽 상단 꼭짓점 좌표 + int base_r = r / 3 * 3; + int base_c = c / 3 * 3; + + for (int i = 0; i < (MAX / 3); i++) { + for (int j = 0; j < (MAX / 3); j++) { + if (sudoku[base_r + i][base_c + j] == n) { + return false; + } + } + } + + return true; +} + +bool check(int r, int c, int n) { + return checkRow(r, n) && checkCol(c, n) && checkSquare(r, c, n); +} + +/** + * (0, 0)부터 차례로 빈칸을 채워나간다 + * + * idx: 왼쪽 상단부터 매긴 칸 번호, (row * 9) + col + */ +void fillSudoku(int idx) { + // 재귀 호출 종료 조건: 스도쿠 판을 다 채운 경우 + if (idx == MAX * MAX) { + is_finished = true; + return; + } + + int r = idx / MAX; + int c = idx % MAX; + + // 빈칸이 아닌 경우 + if (sudoku[r][c] != 0) { + // 바로 다음 칸 탐색 + fillSudoku(idx + 1); + } + // 빈칸인 경우 + else { + // i: 이번 빈칸에 넣을 수 + for (int i = 1; i <= MAX; i++) { + // 불가능한 경우 + if (!check(r, c, i)) { + continue; + } + + sudoku[r][c] = i; + fillSudoku(idx + 1); + if (is_finished) { // 채우기에 성공했으면 + return; // 현재 상태를 출력해야 하므로 원상태로 돌려놓지 않고 즉시 종료 + } + sudoku[r][c] = 0; + } + } +} + +/** + * 모든 빈칸에 1~9를 넣어본다. + * 단, 가로, 세로, 정사각형에 같은 수가 있는 경우는 가지치기해준다. + * 가지치기를 위해 가로 9칸, 세로 9칸, 정사각형 9칸을 모두 탐색한다. + * + * 가지치기 시간 복잡도: O(N) + * 약 245ms + */ +int main() +{ + // 입력 + for (int i = 0; i < MAX; i++) { + for (int j = 0; j < MAX; j++) { + cin >> sudoku[i][j]; + } + } + + // 연산 + fillSudoku(0); + + // 출력 + for (int i = 0; i < MAX; i++) { + for (int j = 0; j < MAX; j++) { + cout << sudoku[i][j] << " "; + } + cout << "\n"; + } + + return 0; +} \ No newline at end of file diff --git "a/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\217\204\354\240\204/2580_v2.cpp" "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\217\204\354\240\204/2580_v2.cpp" new file mode 100644 index 00000000..214930a5 --- /dev/null +++ "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\217\204\354\240\204/2580_v2.cpp" @@ -0,0 +1,112 @@ +#include +#include + +using namespace std; + +const int MAX = 9; + +bool is_finished; +int sudoku[MAX][MAX]; +bool is_in_row[MAX][MAX + 1]; // is_in_row[r][n]: r번 행에 n이 존재하는지 여부 +bool is_in_col[MAX][MAX + 1]; // is_in_col[c][n]: c번 열에 n이 존재하는지 여부 +bool is_in_square[MAX][MAX + 1]; // is_in_square[s][n]: s번 정사각형에 n이 존재하는지 여부 + +/** + * 정사각형 계산 함수 + * (r, c)가 속한 3*3 정사각형의 번호를 리턴 + */ +int calcSquare(int r, int c) { + return (r / 3) * 3 + (c / 3); +} + +void fill(int r, int c, int n) { + sudoku[r][c] = n; + is_in_row[r][n] = true; + is_in_col[c][n] = true; + is_in_square[calcSquare(r, c)][n] = true; +} + +void empty(int r, int c) { + int n = sudoku[r][c]; + sudoku[r][c] = 0; + is_in_row[r][n] = false; + is_in_col[c][n] = false; + is_in_square[calcSquare(r, c)][n] = false; +} + +bool check(int r, int c, int n) { + return !is_in_row[r][n] && !is_in_col[c][n] && !is_in_square[calcSquare(r, c)][n]; +} + +/** + * (0, 0)부터 차례로 빈칸을 채워나간다 + * + * idx: 왼쪽 상단부터 매긴 칸 번호, (row * 9) + col + */ +void fillSudoku(int idx) { + // 재귀 호출 종료 조건: 스도쿠 판을 다 채운 경우 + if (idx == MAX * MAX) { + is_finished = true; + return; + } + + int r = idx / MAX; + int c = idx % MAX; + + // 빈칸이 아닌 경우 + if (sudoku[r][c] != 0) { + // 바로 다음 칸 탐색 + fillSudoku(idx + 1); + } + // 빈칸인 경우 + else { + // i: 이번 빈칸에 넣을 수 + for (int i = 1; i <= MAX; i++) { + // 불가능한 경우 + if (!check(r, c, i)) { + continue; + } + + fill(r, c, i); + fillSudoku(idx + 1); + if (is_finished) { // 채우기에 성공했으면 + return; // 현재 상태를 출력해야 하므로 원상태로 돌려놓지 않고 즉시 종료 + } + empty(r, c); + } + } +} + +/** + * 모든 빈칸에 1~9를 넣어본다. + * 단, 가로, 세로, 정사각형에 같은 수가 있는 경우는 가지치기해준다. + * 가지치기를 위해 각 가로, 세로, 정사각형에 특정 숫자가 존재하는지 여부를 배열로 관리한다. + * + * 가지치기 시간 복잡도: O(1) + * 약 90ms + */ +int main() +{ + int n; + + // 입력 + for (int i = 0; i < MAX; i++) { + for (int j = 0; j < MAX; j++) { + cin >> n; + fill(i, j, n); + } + } + + // 연산 + fillSudoku(0); + + // 출력 + for (int i = 0; i < MAX; i++) { + for (int j = 0; j < MAX; j++) { + cout << sudoku[i][j] << " "; + } + cout << "\n"; + } + + return 0; +} \ No newline at end of file diff --git "a/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\217\204\354\240\204/\354\206\214\354\210\230_\354\260\276\352\270\260.cpp" "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\217\204\354\240\204/\354\206\214\354\210\230_\354\260\276\352\270\260.cpp" new file mode 100644 index 00000000..7cbe3069 --- /dev/null +++ "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\217\204\354\240\204/\354\206\214\354\210\230_\354\260\276\352\270\260.cpp" @@ -0,0 +1,80 @@ +#include +#include +#include + +using namespace std; + +const int MAX_VAL = 1e8; +const int MAX_N = 7; + +int n; +int answer = 0; +int nums[MAX_N]; +bool is_used[MAX_N]; // is_used[i]: i번 조각을 현재 사용중인지 여부 +bool is_counted[MAX_VAL]; // is_counted[i]: i를 카운트 한 적이 있는지 여부 + +bool isPrime(int x) { + if (x == 0 || x == 1) { + return false; + } + + for (long long i = 2; i * i <= x; i++) { + if (x % i == 0) { + return false; + } + } + + return true; +} + +/** + * 총 N개가 될 때까지 종이 조각을 하나씩 뽑아서 이어붙인다. + * N개를 뽑는 중간 과정에서 만들어지는 수(1 ~ (N-1)개의 조각으로 만든)도 체크해주면서 지나가면, + * 종이 조각들로 만들 수 있는 모든 수를 고려하게 된다. + * + * cnt: 현재까지 뽑은 종이 조각 개수 + * val: 현재까지 뽑은 종이 조각으로 만든 수 + */ +void backtrack(int cnt, int val) { + // 현재까지 만든 수가 소수인지 체크 + // cnt == 0인 경우는 아직 아무것도 뽑지 않았으므로 내가 만든 수가 아님에 유의 + if (cnt > 0 && !is_counted[val] && isPrime(val)) { + answer++; + is_counted[val] = true; + } + + // 재귀 호출 종료 조건: N개를 모두 뽑은 경우 + if (cnt == n) { + return; + } + + // i: 다음으로 뽑을 수 + for (int i = 0; i < n; i++) { + if (is_used[i]) { + continue; + } + + is_used[i] = true; + backtrack(cnt + 1, val * 10 + nums[i]); + is_used[i] = false; + } +} + +int solution(string numbers) { + // 입력 처리 + n = numbers.size(); + for (int i = 0; i < n; i++) { + nums[i] = numbers[i] - '0'; + } + + // 연산 + backtrack(0, 0); + + return answer; +} + +int main() { + cout << solution("17"); + + return 0; +} \ No newline at end of file diff --git "a/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/15649.cpp" "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/15649.cpp" new file mode 100644 index 00000000..91e3a323 --- /dev/null +++ "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/15649.cpp" @@ -0,0 +1,56 @@ +#include + +using namespace std; +const int MAX_N = 8; + +int n, m; +int sequence[MAX_N]; +bool is_used[MAX_N + 1]; + +void printSequence() { + for (int i = 0; i < m; i++) { + cout << sequence[i] << " "; + } + cout << "\n"; +} + +/** + * 숫자를 하나씩, 총 M개가 될 때까지 뽑는다. + * + * cnt: 현재까지 고른 숫자의 개수 + */ +void backtrack(int cnt) { + // 재귀 호출 종료 조건: M개의 숫자를 다 뽑은 경우 + if (cnt == m) { + printSequence(); + return; + } + + // i: 고르려는 수 + for (int i = 1; i <= n; i++) { + // 이미 골랐던 숫자라면, 사용 불가 + if (is_used[i]) { + continue; + } + + // 사용 + sequence[cnt] = i; + is_used[i] = true; + + // 다음 숫자 고르기 + backtrack(cnt + 1); + + // 반납 + is_used[i] = false; + } +} + +int main() { + // 입력 + cin >> n >> m; + + // 연산 + backtrack(0); + + return 0; +} \ No newline at end of file diff --git "a/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/9663.cpp" "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/9663.cpp" new file mode 100644 index 00000000..ba9a0e5d --- /dev/null +++ "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/9663.cpp" @@ -0,0 +1,54 @@ +#include + +using namespace std; +const int SIZE = 15; + +int n, ans; +bool is_queen_in_col[SIZE]; +bool is_queen_in_left[SIZE * 2]; +bool is_queen_in_right[SIZE * 2]; + +/** + * 각 행 당 하나의 퀸이 존재하므로 행마다 퀸을 하나씩 놓아본다. + * + * r: 현재 놓으려는 행 + */ +void backtrack(int r) { + // 재귀 호출 종료 조건: N개의 퀸이 모두 놓임 + if (r == n) { + ans++; + return; + } + + // c: 열 + for (int c = 0; c < n; c++) { + // 세로, 좌하향 대각선, 우하향 대각선 모두에 퀸이 없을 경우 -> 퀸 배치 + if (!is_queen_in_col[c] && !is_queen_in_left[r + c] && !is_queen_in_right[r - c + n]) { + // (r, c)에 퀸 배치 -> 그에 따른 열, 좌하향 대각선, 우하향 대각선 체크해줌 + is_queen_in_col[c] = true; + is_queen_in_left[r + c] = true; + is_queen_in_right[r - c + n] = true; + + // 다음 행에도 놓기 + backtrack(r + 1); + + // 재탐색이 가능하도록 놓았던 퀸 회수 + is_queen_in_col[c] = false; + is_queen_in_left[r + c] = false; + is_queen_in_right[r - c + n] = false; + } + } +} + +int main() { + // 입력 + cin >> n; + + // 연산 + backtrack(0); + + // 출력 + cout << ans; + + return 0; +} \ No newline at end of file diff --git "a/08_\353\260\261\355\212\270\353\236\230\355\202\271/\355\225\204\354\210\230/14888.cpp" "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\355\225\204\354\210\230/14888.cpp" new file mode 100644 index 00000000..04f275bd --- /dev/null +++ "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\355\225\204\354\210\230/14888.cpp" @@ -0,0 +1,85 @@ +#include +#include +#include + +using namespace std; + +const int INF = 1e9; +const int MAX_N = 11; +const int ADD = 0, SUB = 1, MUL = 2, DIV = 3; +const int EXP_NUM = 4; + +int n; +int nums[MAX_N]; +int expression[EXP_NUM]; +int max_val = -INF, min_val = INF; + +/** + * 연산자를 하나씩, 총 (N-1)개가 될 때까지 뽑는다. + * + * cnt: 뽑은 연산자의 개수 + * curr_val: 현재 연산값 + */ +void backtrack(int cnt, int curr_val) { + // 재귀 호출 종료 조건: (N-1)개의 연산자를 다 뽑은 경우 + if (cnt == n - 1) { + max_val = max(max_val, curr_val); + min_val = min(min_val, curr_val); + return; + } + + // i: 연산자 번호 + for (int i = 0; i < EXP_NUM; i++) { + // 사용할 연산자가 남아있지 않으면, 사용 불가 + if (expression[i] == 0) { + continue; + } + + // 연산자 사용 + expression[i]--; + int new_sum = 0; + switch (i) { + case ADD: + new_sum = curr_val + nums[cnt + 1]; + break; + case SUB: + new_sum = curr_val - nums[cnt + 1]; + break; + case MUL: + new_sum = curr_val * nums[cnt + 1]; + break; + case DIV: + new_sum = curr_val / nums[cnt + 1]; + break; + } + + // 다음 연산자 선택 + backtrack(cnt + 1, new_sum); + + // 연산자 반납 + expression[i]++; + } +} + +/** + * 모든 연산자 조합을 시도해보면서 최대값과 최솟값을 찾는다. + * 모든 연산자 조합을 만들기 위해 가장 왼쪽에 들어갈 연산자부터 하나씩 선택한다. + */ +int main() { + // 입력 + cin >> n; + for (int i = 0; i < n; i++) { + cin >> nums[i]; + } + for (int i = 0; i < EXP_NUM; i++) { + cin >> expression[i]; + } + + // 연산 + backtrack(0, nums[0]); + + // 출력 + cout << max_val << '\n' << min_val; + + return 0; +} \ No newline at end of file diff --git "a/08_\353\260\261\355\212\270\353\236\230\355\202\271/\355\225\204\354\210\230/14889.cpp" "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\355\225\204\354\210\230/14889.cpp" new file mode 100644 index 00000000..539ad283 --- /dev/null +++ "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\355\225\204\354\210\230/14889.cpp" @@ -0,0 +1,85 @@ +#include +#include +#include + +using namespace std; + +const int MAX_N = 20; +const int INF = 1e9; + +int n; +int min_power_gap = INF; +int s[MAX_N][MAX_N]; +bool is_start[MAX_N]; + +int calcTeamPowerGap() { + int start_power = 0; + int link_power = 0; + + for (int i = 0; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + int ssum = s[i][j] + s[j][i]; + + // i와 j 모두 스타트 팀인 경우 + if (is_start[i] && is_start[j]) { + start_power += ssum; + } + // i와 j 모두 링크 팀인 경우 + else if (!is_start[i] && !is_start[j]) { + link_power += ssum; + } + } + } + + return abs(start_power - link_power); +} + +/** + * 스타트팀원을 한명씩 뽑는다. + * 중복 탐색을 막기 위해 팀원의 번호가 오름차순이 되도록 뽑는다. + * ex) [1, 2]와 [2, 1]은 같은 케이스 이므로 [1, 2]만 탐색 + * + * idx: 남은 사람들 중 가장 빠른 번호 + * cnt: 현재까지 뽑은 사람 수 + */ +void backtrack(int idx, int cnt) { + // 재귀 호출 종료 조건: n/2명을 다 뽑은 경우 + if (cnt == (n / 2)) { + int power_gap = calcTeamPowerGap(); + min_power_gap = min(min_power_gap, power_gap); + return; + } + + // [idx+1, idx+2, ..., n-1] 중에서 다음 팀원을 뽑음 + for (int i = idx; i < n; i++) { + is_start[i] = true; + backtrack(i + 1, cnt + 1); + is_start[i] = false; + } +} + +/** + * 스타트: [1, 2], 링크: [0, 3]인 경우와 + * 스타트: [0, 3], 링크: [1, 2]인 경우는 같다. + * 특정 사람이 있는 팀 / 없는 팀으로만 구별하면 된다. + * 0번이 있는 팀과 없는 팀으로 구별하자. 그리고 0번이 있는 팀을 스타트팀이라고 부르자. + * 스타트팀을 뽑는 모든 조합을 전부 시도해본다. + */ +int main() { + // 입력 + cin >> n; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + cin >> s[i][j]; + } + } + + // 연산 + is_start[0] = true; + backtrack(1, 1); + + // 출력 + cout << min_power_gap << '\n'; + + return 0; +} diff --git "a/08_\353\260\261\355\212\270\353\236\230\355\202\271/\355\225\204\354\210\230/20055.cpp" "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\355\225\204\354\210\230/20055.cpp" new file mode 100644 index 00000000..15c9f153 --- /dev/null +++ "b/08_\353\260\261\355\212\270\353\236\230\355\202\271/\355\225\204\354\210\230/20055.cpp" @@ -0,0 +1,106 @@ +#include +#include + +using namespace std; + +struct info { // 내구도와 로봇 존재 여부 + int power; + bool is_on; +}; + +/* 벨트를 한 칸 회전*/ +void rotateBelt(deque &belt, int n) { + belt.push_front(belt.back()); + belt.pop_back(); + belt[n - 1].is_on = false; // 로봇이 내리는 위치 +} + +/* 로봇을 움직일 수 있으면 한 칸 이동*/ +void moveRobot(deque &belt, int n) { + for (int i = n - 2; i >= 0; i--) { // 배열 접근 가능 범위가 0 ~ n-1 인데 다음 칸과 비교해야 하니까 0 ~ n-2 + if (belt[i].is_on && (!belt[i + 1].is_on) && (belt[i + 1].power >= 1)) { + // 지금 칸에 로봇이 존재하고, 다음 칸에 로봇이 없으며, 다음 칸에 내구도가 남아있을 때 + belt[i].is_on = false; + belt[i + 1].is_on = true; + belt[i + 1].power--; + } + belt[n - 1].is_on = false; // 로봇이 내리는 위치 + } +} + +/* 올리는 칸에 로봇을 올릴 수 있으면 올림 */ +void putRobot(deque &belt) { + if (!belt[0].is_on && belt[0].power >= 1) { + // 올리는 칸에 로봇이 존재하지 않고, 내구도가 남아있으면 + belt[0].is_on = true; + belt[0].power--; + } +} + +/* 벨트의 내구도 체크 */ +bool checkFinish(deque &belt, int n, int k) { + int count = 0; + for (int i = 0; i < 2 * n; i++) { + if (belt[i].power == 0) { + count++; + } + } + + if (count >= k) { + return true; + } + return false; +} + +int solution(deque &belt, int n, int k) { + int step = 1; + while (true) { + // 회전 + rotateBelt(belt, n); + // 이동 + moveRobot(belt, n); + // 로봇 올리기 + putRobot(belt); + + // 내구도 체크하기 + if (checkFinish(belt, n, k)) { + return step; + } + step++; + } +} + + +/** + * [컨베이어 벨트 위의 로봇 문제] + * 1. 벨트가 각 칸 위의 로봇과 함께 한 칸 회전 + * 2. 가장 먼저 벨트에 올라간 로봇부터, 벨트 회전 방향으로 한 칸 이동할 수 있다면 이동 + * (이동가능: 이동하려는 칸에 로봇이 없고, 그 칸의 내구도가 1 이상이어야 함) + * 3. 올리는 위치에 있는 칸의 내구도가 0이 아니면 올리는 위치에 로봇 올림 + * 4. 내구도가 0인 칸의 개수가 k개 이상이라면 과정 종료. 그렇지 않다면 1로 돌아감 + * -> 1 ~ 3까지가 1단계 + * + * [문제 풀이] + * 회전과 관련이 깊은 자료구조 deque를 사용하여 풀이 + * + * 1번 벨트 회전: 벨트의 마지막 원소를 벨트 처음에 넣기 + * 2번 로봇 이동: 가장 먼저 올라간 로봇부터 고려해야 하므로 (내리는 위치 - 1)부터 (올리는 위치)까지 검사 + * -> 로봇 옮기는거 가능하면 존재여부 체크하고 내구도 감소 + * 3번 로봇 추가: 올리는 위치 칸 내구도 0이 아니라면 해당 칸 로봇 존재 여부 체크 + 내구도 감소 + * + * + * >> 주의: 칸 번호를 1번이 아닌 0번부터 시작하는 것으로 관리하고 있기 때문에, n번 칸이 아니라 n-1번 칸이 내리는 위치 << + */ + +int main() { + // 입력 + int n, k; + cin >> n >> k; + deque belt(2 * n); // 컨베이어 벨트의 내구도와 로봇 존재 여부 저장 + for (int i = 0; i < 2 * n; i++) { + cin >> belt[i].power; + belt[i].is_on = false; + } + // 연산 & 출력 + cout << solution(belt, n, k); +} \ No newline at end of file diff --git "a/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/README.md" "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/README.md" new file mode 100644 index 00000000..00305430 --- /dev/null +++ "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/README.md" @@ -0,0 +1,76 @@ +# 동적 계획법 (Dynamic Programming) + +[메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4) + +## 💻 튜터링 + +### 라이브 코딩 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :----------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :----------: | :--------: | +| 2579 | 계단 오르기 | | [바로가기](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/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/2579.cpp) | DP | +| 12865 | 평범한 배낭 | | [바로가기](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/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/12865.cpp) | DP | +| 11660 | 구간 합 구하기 5 | | [바로가기](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/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/11660.cpp) | DP, 누적합 | + +## ✏️ 과제 + +### 마감기한 + +~ 5 / 1 (월) 23:59 - 과제 제출
+~ 5 / 4 (목) 23:59 - 추가 제출
+ +### 필수 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :------------------------: | +| 20923 | 숫자 할리갈리 게임 | | [C++](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/%ED%95%84%EC%88%98/20923.cpp) | 구현, 시뮬레이션, 자료구조 | +| 11726 | 2xn 타일링 | | [C++](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/%ED%95%84%EC%88%98/11726.cpp) | DP | +| 1149 | RGB거리 | | [C++](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/%ED%95%84%EC%88%98/1149.cpp) | DP | + +### 도전 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :--------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :--: | +| 프로그래머스 | 가장 큰 정사각형 찾기 | **Lv.2** | [C++](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/%EB%8F%84%EC%A0%84/%EA%B0%80%EC%9E%A5_%ED%81%B0_%EC%A0%95%EC%82%AC%EA%B0%81%ED%98%95.cpp) | DP | +| 9084 | 동전 | | [C++](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/%EB%8F%84%EC%A0%84/9048.cpp) | DP | + +--- + +### 힌트 + +
+숫자 할리갈리 게임 +
+    카드를 어떤 자료구조로 관리하면 좋을까요? 게임을 반복해서 진행하네요. 함수화를 통해 효율적으로 코드를 작성할 수 있을 것 같아요! 덱이 비어있는 경우에 주의하세요! +
+
+ +
+2xn 타일링 +
+    가장 마지막 세로줄을 채울 수 있는 방법이 총 몇 가지 있나요? +
+
+ +
+RGB거리 +
+    1차원 DP 배열로 해결이 가능할까요? +
+
+ +
+가장 큰 정사각형 찾기 +
+    라이브 코딩의 11660번 문제 접근법을 복습해보아요. +
+
+ +
+동전 +
+    라이브 코딩의 계단 문제와 비슷한 느낌이 들지 않나요? 점화식을 잘 세워보면 쉽게 풀릴 것 같아요. +
+
+ +--- diff --git "a/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\352\260\225\354\235\230 \354\236\220\353\243\214/09_\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\352\260\225\354\235\230 \354\236\220\353\243\214/09_\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" new file mode 100644 index 00000000..b60caa0c Binary files /dev/null and "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\352\260\225\354\235\230 \354\236\220\353\243\214/09_\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" differ diff --git "a/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\352\260\225\354\235\230 \354\236\220\353\243\214/09_\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225_\354\235\264\353\241\240.pdf" "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\352\260\225\354\235\230 \354\236\220\353\243\214/09_\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225_\354\235\264\353\241\240.pdf" new file mode 100644 index 00000000..7c791730 Binary files /dev/null and "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\352\260\225\354\235\230 \354\236\220\353\243\214/09_\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225_\354\235\264\353\241\240.pdf" differ diff --git "a/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\217\204\354\240\204/9048.cpp" "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\217\204\354\240\204/9048.cpp" new file mode 100644 index 00000000..1c5c9ab4 --- /dev/null +++ "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\217\204\354\240\204/9048.cpp" @@ -0,0 +1,57 @@ +#include +#include + +using namespace std; + +int countNumberOfCases(int n, int m, vector& coins) { + // dp[i]: i원을 만드는 경우의 수 + vector dp(m + 1, 0); + + // 0원을 만드는 경우의 수는 1가지 + dp[0] = 1; + + // i: 고려하고 있는 동전 번호 + // j: 목표 금액 + for (int i = 0; i < n; i++) { + for (int j = coins[i]; j <= m; j++) { + // i번 동전을 사용하지 않으면, 남은 금액 j를 만들어야 함 + // i번 동전 하나를 사용하면, 남은 금액 (j - coins[i])을 만들어야 함 + dp[j] = dp[j] + dp[j - coins[i]]; + } + } + + return dp[m]; +} + +/** + * dp[i] = 주어진 동전 종류를 사용해서 i원을 만드는 경우의 수 + * + * dp[0] = 1 을 넣고 시작 (0원을 만드는 경우의 수 1로 생각) + * 각 동전마다 해당 동전부터 만들어야 하는 금액(m)까지 돌리면서 해당 동전을 사용하기 전 금액의 경우의 수와 현재 경우의 수를 더함 + * 해당 동전 사용하기 전 금액의 경우의 수가 0이면 금액을 만들 수 없는 경우이지만, 어차피 더해도 값 변화는 없으므로 따로 고려하지 않음 + */ + +int main() { + int t; + + cin >> t; + while (t--) { + int n, m; + + // 입력 + cin >> n; + vector coins(n); + for (int i = 0; i < n; i++) { + cin >> coins[i]; + } + cin >> m; + + // 연산 + int answer = countNumberOfCases(n, m, coins); + + // 출력 + cout << answer << "\n"; + } + + return 0; +} \ No newline at end of file diff --git "a/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\217\204\354\240\204/\352\260\200\354\236\245_\355\201\260_\354\240\225\354\202\254\352\260\201\355\230\225.cpp" "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\217\204\354\240\204/\352\260\200\354\236\245_\355\201\260_\354\240\225\354\202\254\352\260\201\355\230\225.cpp" new file mode 100644 index 00000000..ea7ba713 --- /dev/null +++ "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\217\204\354\240\204/\352\260\200\354\236\245_\355\201\260_\354\240\225\354\202\254\352\260\201\355\230\225.cpp" @@ -0,0 +1,64 @@ +#include +#include +#include + +using namespace std; + +int maxSquare(int row, int col, vector>& board) { + // dp[i][j]: (i, j)를 우측하단 꼭짓점으로 하는 가장 큰 정사각형의 한 변의 길이 + vector> dp(row + 1, vector(col + 1, 0)); + int ret = 0; + + for (int i = 1; i <= row; i++) { + for (int j = 1; j <= col; j++) { + // 꼭짓점이 0인 경우, 정사각형의 크기는 0 + if (board[i - 1][j - 1] == 0) { + continue; + } + + // 북서쪽(↖) 정사각형, 북쪽(↑) 정사각형, 서쪽(←) 정사각형으로 쪼갤 수 있음, + // 그 중 가장 작은 정사각형의 한 변의 길이 X에 맞춰 자른 뒤 + // (i, j)를 꼭짓점으로 한 칸 추가하면 한 변의 길이가 (X+1)인 정사각형이 됨 + dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1; + ret = max(ret, dp[i][j]); // 최대값 갱신 + } + } + + return ret * ret; +} + +/** + * 정사각형은 다음과 같이 쪼갤 수 있음 + * ex. 4x4 정사각형 + * = (↖ 3x3 정사각형) + (↑ 3x3 정사각형) + (← 3x3 정사각형) + (오른쪽 아래 1x1 정사각형) + * + * 1 1 1 1 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0 + * 1 1 1 1 = 1 1 1 0 + 0 1 1 1 + 1 1 1 0 + 0 0 0 0 + * 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 + * 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 + * + * 따라서 dp[i][j]: (i, j)를 우측하단 꼭짓점으로 하는 가장 큰 정사각형의 한 변의 길이 라고 하면 + * dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]} + 1 + */ +int solution(vector> board) +{ + int row = board.size(); + int col = board[0].size(); + + int answer = maxSquare(row, col, board); + + return answer; +} + +int main() { + vector> board = + { + {0, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {0, 0, 1, 0} + }; + cout << solution(board); + + return 0; +} \ No newline at end of file diff --git "a/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11660.cpp" "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11660.cpp" new file mode 100644 index 00000000..0b978685 --- /dev/null +++ "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11660.cpp" @@ -0,0 +1,55 @@ +#include +#include +#include + +using namespace std; + +void calcPsum(int n, vector>& A, vector>& psum) { + // psum[i][j]: (1,1)부터 (i,j)까지의 합 + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + psum[i][j] = psum[i - 1][j] + psum[i][j - 1] - psum[i - 1][j - 1] + A[i][j]; + } + } +} + +int calcSum(int x1, int y1, int x2, int y2, vector>& psum) { + return psum[x2][y2] - psum[x2][y1 - 1] - psum[x1 - 1][y2] + psum[x1 - 1][y1 - 1]; +} + +int main() { + // 빠른 입출력 + ios_base::sync_with_stdio(); + cin.tie(NULL); cout.tie(NULL); + + int n, m; + + // 입력: 데이터 + cin >> n >> m; + vector> A(n + 1, vector(n + 1, 0)); + vector> psum(n + 1, vector(n + 1, 0)); + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + cin >> A[i][j]; + } + } + + // 연산: 누적합 테이블 구해두기 + calcPsum(n, A, psum); + + // 쿼리 + for (int i = 0; i < m; i++) { + int x1, y1, x2, y2; + + // 입력 + cin >> x1 >> y1 >> x2 >> y2; + + // 연산 + int answer = calcSum(x1, y1, x2, y2, psum); + + // 출력 + cout << answer << "\n"; + } + + return 0; +} \ No newline at end of file diff --git "a/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/12865.cpp" "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/12865.cpp" new file mode 100644 index 00000000..4bb1d4b8 --- /dev/null +++ "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/12865.cpp" @@ -0,0 +1,69 @@ +#include +#include + +using namespace std; + +// 1차원 DP 배열 사용 +int knapsack1(int n, int k, vector& w, vector& v) { + // dp[i]: 준서가 버틸 수 있는 무게가 i일 때, 물건들을 넣어 얻을 수 있는 가치합의 최대값 + vector dp(k + 1, 0); + + // i: 현재 넣으려는 물건 + // j: 버틸 수 있는 무게 + for (int i = 1; i <= n; i++) { + for (int j = k; j >= w[i]; j--) { + // 물건을 넣는 경우 vs. 넣지 않는 경우 + int packing = dp[j - w[i]] + v[i]; + int not_packing = dp[j]; + dp[j] = max(packing, not_packing); + } + } + + return dp[k]; +} + +// 2차원 DP 배열 사용 +int knapsack2(int n, int k, vector& w, vector& v) { + // dp[i][j]: 준서가 버틸 수 있는 무게가 j일 때, 1~i번 물건들을 넣어 얻을 수 있는 가치합의 최대값 + vector> dp(n + 1, vector(k + 1, 0)); + + // i: 현재 넣으려는 물건 + // j: 버틸 수 있는 무게 + for (int i = 1; i <= n; i++) { + // 버틸 수 있는 무게 < 물건 무게 + for (int j = 0; j < w[i]; j++) { + // 무조건 넣지 못함 + dp[i][j] = dp[i - 1][j]; + } + + // 버틸 수 있는 무게 >= 물건 무게 + for (int j = w[i]; j <= k; j++) { + // 물건을 넣는 경우 vs. 넣지 않는 경우 + int packing = dp[i - 1][j - w[i]] + v[i]; + int not_packing = dp[i - 1][j]; + dp[i][j] = max(packing, not_packing); + } + } + + return dp[n][k]; +} + +int main() { + int n, k; + + // 입력 + cin >> n >> k; + vector w(n + 1); + vector v(n + 1); + for (int i = 1; i <= n; i++) { + cin >> w[i] >> v[i]; + } + + // 연산 + int answer = knapsack1(n, k, w, v); + + // 출력 + cout << answer; + + return 0; +} \ No newline at end of file diff --git "a/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2579.cpp" "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2579.cpp" new file mode 100644 index 00000000..e533262c --- /dev/null +++ "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2579.cpp" @@ -0,0 +1,41 @@ +#include +#include + +using namespace std; + +int maxScore(int n, vector &score) { + // dp[i]: i번째 계단에 도착했을 때 점수의 최대값 + vector dp(n + 1, 0); + + // 두 번째 계단까지는 모든 칸을 밟고 오는 것이 최대 + dp[1] = score[1]; + dp[2] = score[1] + score[2]; + + for (int i = 3; i <= n; i++) { + // 한 칸 전에서 온 경우 vs. 두 칸 전에서 온 경우 + int one_step_before = dp[i - 3] + score[i - 1]; // 세 칸을 연속으로 밟을 수 없으므로 + int two_steps_before = dp[i - 2]; + dp[i] = max(one_step_before, two_steps_before) + score[i]; + } + + return dp[n]; +} + +int main() { + int n; + + // 입력 + cin >> n; + vector score(n + 1, 0); + for (int i = 1; i <= n; i++) { + cin >> score[i]; + } + + // 연산 + int answer = maxScore(n, score); + + // 출력 + cout << answer; + + return 0; +} \ No newline at end of file diff --git "a/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\355\225\204\354\210\230/1149.cpp" "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\355\225\204\354\210\230/1149.cpp" new file mode 100644 index 00000000..28d6e481 --- /dev/null +++ "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\355\225\204\354\210\230/1149.cpp" @@ -0,0 +1,45 @@ +#include +#include +#include + +using namespace std; + +const int R = 0, G = 1, B = 2; + +int paint(int n, vector>& houses) { + // dp[i][j]: i번째 집은 j색으로 칠할 때, 1~i번 집까지 칠하는 최소 비용 + vector> dp(n + 1, vector(3, 0)); + + for (int i = 1; i <= n; i++) { + // (i-1)번 집은 남은 두 색상 중 하나로 칠해야 함 + dp[i][R] = min(dp[i - 1][G], dp[i - 1][B]) + houses[i][R]; + dp[i][G] = min(dp[i - 1][B], dp[i - 1][R]) + houses[i][G]; + dp[i][B] = min(dp[i - 1][R], dp[i - 1][G]) + houses[i][B]; + } + + return min({dp[n][R], dp[n][G], dp[n][B]}); +} + +/** + * 1번집 부터 차례로 색칠합니다. + * 만약 i번 집을 빨간색으로 칠한다면, (i-1)번 집을 초록색이나 파란색으로 칠했어야 합니다. + * 초록색과 파란색 중 더 비용이 적게 드는 색을 선택하면 됩니다. + */ +int main() { + int n; + + // 입력 + cin >> n; + vector> houses(n + 1, vector(3, 0)); + for (int i = 1; i <= n; i++) { + cin >> houses[i][R] >> houses[i][G] >> houses[i][B]; + } + + // 연산 + int answer = paint(n, houses); + + // 출력 + cout << answer; + + return 0; +} \ No newline at end of file diff --git "a/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\355\225\204\354\210\230/11726.cpp" "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\355\225\204\354\210\230/11726.cpp" new file mode 100644 index 00000000..ea797065 --- /dev/null +++ "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\355\225\204\354\210\230/11726.cpp" @@ -0,0 +1,47 @@ +#include +#include + +using namespace std; + +int countNumberOfCases(int n) { + const int MOD = 10'007; + // dp[i]: 2xi 크기의 직사각형을 채우는 방법의 수 + vector dp(n+1); + + dp[1] = 1; // 세로로 한 개만 + dp[2] = 2; // 세로로 두 개 or 가로로 두 개 + + for (int i = 3; i <= n; i++) { + int vertical = dp[i - 1]; // 세로로 한 개 놓는 경우 + int horizontal = dp[i - 2]; // 가로로 두 개 놓는 경우 + dp[i] = (vertical + horizontal) % MOD; // 오버플로우 방지를 위해 MOD 연산 + } + + return dp[n]; +} + +/** + * 가장 마지막 세로줄을 채울 수 있는 방법을 살펴봅시다. + * 1. 세로로 한 개를 놓는다. + * 2. 가로로 두 개를 놓는다. + * + * 1번 방법으로 마지막 세로줄을 채울 경우, 남은 부분의 크기는 2 x (n-1) + * 2번 방법으로 마지막 세로줄을 채울 경우, 남은 부분의 크기는 2 x (n-2) + * + * 따라서 2 x n 크기의 직사각형을 채우는 방법의 수는 + * d[i] = dp[i - 1] + dp[i - 2] + */ +int main() { + int n; + + // 입력 + cin >> n; + + // 연산 + int answer = countNumberOfCases(n); + + // 출력 + cout << answer; + + return 0; +} \ No newline at end of file diff --git "a/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\355\225\204\354\210\230/20923.cpp" "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\355\225\204\354\210\230/20923.cpp" new file mode 100644 index 00000000..99a26c27 --- /dev/null +++ "b/09_\353\217\231\354\240\201 \352\263\204\355\232\215\353\262\225/\355\225\204\354\210\230/20923.cpp" @@ -0,0 +1,94 @@ +#include +#include +#include + +using namespace std; + +typedef vector> cards; +const int DO = 0, SU = 1; + +// 승리 판단하기 +string judge(cards& deck) +{ + int do_deck = deck[DO].size(), su_deck = deck[SU].size(); + if (do_deck > su_deck) { + return "do"; + } + else if (do_deck < su_deck) { + return "su"; + } + return "dosu"; +} + +// 그라운드에서 덱으로 카드 옮기기 +void groundToDeck(deque& deck, deque& ground) { + while (!ground.empty()) { + deck.push_back(ground.back()); + ground.pop_back(); + } +} + +// 종을 쳤을 때 +void ringTheBell(int player, cards& deck, cards& ground) { + groundToDeck(deck[player], ground[!player]); // 카드 가져가기 (상대 그라운드 -> 본인 덱) + groundToDeck(deck[player], ground[player]); // 카드 가져가기 (본인 그라운드 -> 본인 덱) +} + + +// 종을 울릴 수 있는 사람 판단 +int whoCanRingTheBell(cards& deck, cards& ground) { + if (!ground[DO].empty() && ground[DO].front() == 5) { // 도도 + return DO; + } + else if (!ground[SU].empty() && ground[SU].front() == 5) { // 도도 + return DO; + } + else if (!ground[DO].empty() && !ground[SU].empty() && (ground[DO].front() + ground[SU].front() == 5)) { // 수연 + return SU; + } + return -1; // 종을 울릴 수 없음 +} + +// 게임 진행 +string game(int m, cards& deck, cards& ground) { + bool turn = DO; // 도도 먼저 + while (m--) + { + ground[turn].push_front(deck[turn].front()); // 카드 내려놓기(덱 -> 그라운드) + deck[turn].pop_front(); + if (deck[turn].empty()) { + break; + } + int bell = whoCanRingTheBell(deck, ground); // 종을 울릴 수 있는 사람 + if (bell != -1) { // 종을 울린 경우 + ringTheBell(bell, deck, ground); + } + turn = !turn; // 차례 바꾸기 + } + return judge(deck); +} + +/* +* 도도, 수연이 각각 덱과 그라운드를 가짐 +* 도도->수연->도도->수연... 순으로 차례를 바꿔가며 게임 진행 (game 함수) +* 1. 카드를 덱에서 한 장 내려놓음 +* 2. 어떤 플레이어가 종을 칠 수 있는지 판단 (whoCanRingTheBell 함수) +* 3. 종을 친 경우 그라운드의 카드를 덱으로 이동(ringTheBell, groundToDeck 함수) +* 종료 조건 만족 시 승리한 사람 리턴(judge 함수) +*/ + +int main() +{ + int n, m, card1, card2; + cards deck(2), ground(2); // 0: 도도, 1: 수연 + // 입력 + cin >> n >> m; + while (n--) { + cin >> card1 >> card2; + deck[DO].push_front(card1); + deck[SU].push_front(card2); + } + // 출력 & 연산 + cout << game(m, deck, ground) << '\n'; + return 0; +} \ No newline at end of file diff --git "a/09_\353\260\261\355\212\270\353\236\230\355\202\271/README.md" "b/09_\353\260\261\355\212\270\353\236\230\355\202\271/README.md" deleted file mode 100644 index e69de29b..00000000 diff --git "a/09_\353\260\261\355\212\270\353\236\230\355\202\271/\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/09_\353\260\261\355\212\270\353\236\230\355\202\271/\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/09_\353\260\261\355\212\270\353\236\230\355\202\271/\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/09_\353\260\261\355\212\270\353\236\230\355\202\271/\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/09_\353\260\261\355\212\270\353\236\230\355\202\271/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" "b/09_\353\260\261\355\212\270\353\236\230\355\202\271/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\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/09_\353\260\261\355\212\270\353\236\230\355\202\271/\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/09_\353\260\261\355\212\270\353\236\230\355\202\271/\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/10_\354\235\264\353\266\204 \355\203\220\354\203\211/README.md" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/README.md" index e69de29b..0fc99b42 100644 --- "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/README.md" +++ "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/README.md" @@ -0,0 +1,77 @@ +# 이분 탐색 (Binary Search) + +[메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4) + +## 💻 튜터링 + +### 라이브 코딩 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :----------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :----------: | :--------: | +| 1920 | 수 찾기 | | [바로가기](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/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/1920.cpp) | 이분탐색, 정렬 | +| 10816 | 숫자 카드 2 | | [바로가기](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/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/10816.cpp) | 이분탐색, 정렬, 해시를 이용한 집합과 맵 | +| 2110 | 공유기 설치 | | [바로가기](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/%EB%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/2110.cpp) | 이분 탐색, 매개 변수 탐색 | + +## ✏️ 과제 + +### 마감기한 + +~ 5 / 9 (화) 18:59 - 과제 제출
+~ 5 / 11 (목) 23:59 - 추가 제출
+ +### 필수 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :------------------------: | +| 14500 | 테트로미노 | | [C++](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/%ED%95%84%EC%88%98/14500.cpp) | 구현, 브루트 포스 | +| 10815 | 숫자 카드 | | [C++](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/%ED%95%84%EC%88%98/10815.cpp) | 자료구조, 정렬, 이분 탐색 | +| 16401 | 과자 나눠주기 | | [C++](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/%ED%95%84%EC%88%98/16401.cpp) | 이분 탐색, 매개 변수 탐색 | + +### 도전 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :--------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :--: | +| 2343 | 기타 레슨 | | [C++](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/%EB%8F%84%EC%A0%84/2343.cpp) | 이분 탐색, 매개 변수 탐색 | +| 3079 | 입국심사 | | [C++](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/%EB%8F%84%EC%A0%84/3079.cpp) | 이분 탐색, 매개 변수 탐색 | + +--- + +### 힌트 + +
+테트로미노 +
+    테트로미노의 모양은 탐색의 관점에서 특징이 있는 것 같아요! +
+
+ +
+숫자 카드 +
+    라이브 코딩 문제를 복습하며 풀어봅시다. 찾아야 할 게 무엇일까요? +
+
+ +
+과자 나눠주기 +
+    막대 과자는 길이와 상관없이 여러 조각으로 나눠질 수 있어요! +
+
+ +
+기타 레슨 +
+    블루레이 크기의 범위는 무엇일까요? +
+
+ +
+입국심사 +
+    라이브 코딩 때 풀어본 공유기 설치 문제와 유사해보이네요. 어떤 값을 기준으로 탐색하여 무엇을 비교해야 할지 생각해보세요 :) +자료형의 범위에 유의해주세요 +
+
+ +--- diff --git "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\352\260\225\354\235\230 \354\236\220\353\243\214/10_\354\235\264\353\266\204\355\203\220\354\203\211_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\352\260\225\354\235\230 \354\236\220\353\243\214/10_\354\235\264\353\266\204\355\203\220\354\203\211_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" new file mode 100644 index 00000000..cfb78cc5 Binary files /dev/null and "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\352\260\225\354\235\230 \354\236\220\353\243\214/10_\354\235\264\353\266\204\355\203\220\354\203\211_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" differ diff --git "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\352\260\225\354\235\230 \354\236\220\353\243\214/10_\354\235\264\353\266\204\355\203\220\354\203\211_\354\235\264\353\241\240.pdf" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\352\260\225\354\235\230 \354\236\220\353\243\214/10_\354\235\264\353\266\204\355\203\220\354\203\211_\354\235\264\353\241\240.pdf" new file mode 100644 index 00000000..43bc9ded Binary files /dev/null and "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\352\260\225\354\235\230 \354\236\220\353\243\214/10_\354\235\264\353\266\204\355\203\220\354\203\211_\354\235\264\353\241\240.pdf" differ diff --git "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\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/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\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/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\217\204\354\240\204/2343.cpp" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\217\204\354\240\204/2343.cpp" new file mode 100644 index 00000000..6f55f40b --- /dev/null +++ "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\217\204\354\240\204/2343.cpp" @@ -0,0 +1,50 @@ +#include +#include +#include + +using namespace std; + +/* +* 적절한 블루레이의 크기를 매개변수 탐색을 이용해 찾습니다. +* 이 때, 각 블루레이의 크기는 최대 강의 길이(maxLen) 이상, 강의 길이의 합(sumLen) 이하임을 이용합니다. +*/ + +int findSize(int&left, int right, vector lesson, int n, int m) { + // 적절한 블루레이의 크기를 이진탐색을 이용해 찾기 + while (left <= right) { + int mid = (left + right) / 2; // mid(찾는 값): 블루레이 크기 후보 + int count = 0; // 블루레이의 개수 + int sum_blue = 0; // 각 블루레이의 크기 + + for (int i = 0; i < n; i++) { + if (sum_blue + lesson[i] > mid) { + count++; + sum_blue = 0; + } + sum_blue += lesson[i]; + } + count++; + // 사이즈가 mid일 때의 블루레이 개수가 m보다 작거나 같으면 더 작은 사이즈로 가정하고 탐색 + // 반대의 경우, 더 큰 값으로 가정하고 대해 탐색 + (count <= m) ? right = mid - 1 : left = mid + 1; + } + return left; +} + +int main() { + int n, m, sum_len = 0, max_len = 0; + // 강의의 수, 블루레이의 수 입력 + cin >> n >> m; + + // 강의 동영상 길이 입력받을 벡터 + vector lesson(n); + // 강의 동영상의 길이 입력 + for (int i = 0; i < n; i++) { + cin >> lesson[i]; + sum_len += lesson[i]; // 강의 길이의 합 갱신 + max_len = max(lesson[i], max_len); // 강의 길이의 최댓값 갱신 + } + // 연산 & 출력 + cout << findSize(max_len, sum_len, lesson, n, m); + return 0; +} \ No newline at end of file diff --git "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\217\204\354\240\204/3079.cpp" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\217\204\354\240\204/3079.cpp" new file mode 100644 index 00000000..8923f205 --- /dev/null +++ "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\217\204\354\240\204/3079.cpp" @@ -0,0 +1,64 @@ +#include +#include +#include + +using namespace std; + +typedef long long ll; +const int MAX = 1e5; + +/* +* 매개변수 탐색을 이용하여 입국 심사에 걸리는 시간을 계산합니다. +* 각 입국 심사에 걸리는 시간에 따라 심사가능한 인원을 계산한 후, 일행 인원과 비교해가며 진행합니다. +*/ + +ll paramSearch(ll &m, ll &n, vector& times, ll &max_wait) { + // 최소 시간: 0, 최대 대기 시간: 최대 단일 대기시간*m + ll left = 0, right = max_wait*m; + // 대기 시간의 최댓값으로 설정 후 값을 줄여갑니다 + ll result = right; + + while (left <= right) { + ll mid = (left + right) / 2; + ll sum = 0; // mid만큼 기다릴 때, 입국심사 가능한 인원 + for (int i = 0; i < n; i++) { + sum += mid / times[i]; + if (sum > m){ + break; + } + } + // 입국심사 가능한 인원이 일행 수보다 크거나 같은 경우 -> 더 적게 기다릴 수도 있음 + if (sum >= m) { + result = min(result, mid); + right = mid - 1; + } + // 입국심사 가능한 인원이 일행 수보다 작은 경우 -> 더 오래 기다려야 함 + else { + left = mid + 1; + } + } + return result; +} + +int main(void) { + ios_base::sync_with_stdio(0); + cin.tie(0); cout.tie(0); + + ll n, m; + ll max_wait = -1; + vector times(MAX+1); + + // 입력 + cin >> n >> m; + + // 입국심사에 걸리는 시간 입력 + for (int i = 0; i < n; i++) { + cin >> times[i]; + max_wait = max(max_wait, times[i]); + } + sort(times.begin(), times.begin()+n); + + // 연산 & 출력 + cout << paramSearch(m, n, times, max_wait); + return 0; +} \ No newline at end of file diff --git "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\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/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\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/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/10816.cpp" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/10816.cpp" new file mode 100644 index 00000000..cd8029ab --- /dev/null +++ "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/10816.cpp" @@ -0,0 +1,79 @@ +#include +#include +#include + +using namespace std; +/* +* lower bound, upper bound를 구한 뒤, 둘의 차이를 구해주면 됩니다. +*/ + +//lower bound +int lowerBound(int left, int right, int target, vector& arr) { + while (left <= right) { + int mid = (left + right) / 2; + // 중간값이 target보다 크다면 target은 왼쪽에 있음 + // 중간값이 target과 같다면 왼쪽에 target과 같은 값이 더 있을 수 있음 + if (arr[mid] >= target) { + right = mid - 1; + } + else { // 중간값이 target보다 작다면 target은 오른쪽에 있음 + left = mid + 1; + } + } + /* + * left를 리턴하는 이유 + * break 조건: left 포인터가 right 포인터보다 뒤에 있는 경우 + * arr[mid] <= target일 때, left 포인터가 이동하고 break + * 이 때 left값은 target이 되는 첫 지점 즉 lower bound임 + */ + return left; +} + +//upper bound +int upperBound(int left, int right, int target, vector& arr) { + while (left <= right) { + int mid = (left + right) / 2; + // 중간값이 target보다 작다면 target은 오른쪽에 있음 + // 중간값이 target과 같다면 오른쪽에 target과 같은 값이 더 있을 수 있음 + if (arr[mid] <= target) { + left = mid + 1; + } + else { // 중간값이 target보다 크다면 target은 왼쪽에 있음 + right = mid - 1; + } + } + /** + * left를 리턴하는 이유 + * break 조건: left 포인터가 right 포인터보다 뒤에 있는 경우 + * arr[mid] == target 일 때 left가 target을 초과하는 순간 break + * 이 때의 left 값이 upper bound + */ + return left; +} + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(NULL); + cout.tie(NULL); + + int n, m, input; + + //입력 + cin >> n; + vector arr(n, 0); + for (int i = 0; i < n; i++) { + cin >> arr[i]; + } + + //이분 탐색을 하기 위해 정렬 + sort(arr.begin(), arr.end()); + + //입력 + cin >> m; + while (m--) { + cin >> input; + //연산 & 출력 + cout << upperBound(0, n - 1, input, arr) - lowerBound(0, n - 1, input, arr) << ' '; + } + return 0; +} \ No newline at end of file diff --git "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/1920.cpp" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/1920.cpp" new file mode 100644 index 00000000..8c76ea77 --- /dev/null +++ "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/1920.cpp" @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +using namespace std; +/* +* 이분탐색을 이용해 입력으로 주어진 키 값의 존재 여부를 구합니다 +*/ + +int binarySearch(int n, int key, vector &nums) { + int left = 0; + int right = n - 1; + int mid; + // 키 값의 존재여부 구하기 + while (left <= right) { + mid = (left + right) / 2; + if (nums[mid] == key) { // key 값이 배열의 중앙값과 같을 때 + return 1; + } + else if (nums[mid] > key) { // key 값이 배열의 중앙값보다 작을 때-> 더 작은 값 탐색 + right = mid - 1; + } + else { // key 값이 배열의 중앙값보다 클때-> 더 큰 값 탐색 + left = mid + 1; + } + } + return 0; +} + +int main(void) { + cin.tie(0); cout.tie(0); + ios_base::sync_with_stdio(NULL); + + int n, m, key; + // 입력 + cin >> n; + vector nums(n); // 자연수의 최대 개수가 100000이므로 해당 크기의 배열을 만들기 + for (int i = 0; i < n; i++) { + cin >> nums[i]; + } + sort(nums.begin(), nums.end()); // quick sort를 이용해 배열 오름차순으로 정렬 + // 입력 + cin >> m; + while(m--) { + cin >> key; + // 연산 & 출력 + cout << binarySearch(n, key, nums) << '\n'; + } + return 0; +} diff --git "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2110.cpp" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2110.cpp" new file mode 100644 index 00000000..4a22d19a --- /dev/null +++ "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2110.cpp" @@ -0,0 +1,57 @@ +#include +#include +#include + +using namespace std; + +// 가장 인접한 두 공유기 사이의 거리가 dist가 되도록 공유기를 설치했을 때, 설치된 공유기 개수 +int cntRouter(int dist, vector& router) { + // 첫번째 집에 무조건 공유기 설치 + int cnt = 1; + int cur = router[0]; + + for (int i = 1; i < router.size(); i++) { + if (router[i] - cur >= dist) { // 가장 가까운 집과의 거리가 dist 이상이라면 + cnt++; // 공유기 설치 + cur = router[i]; + } + } + return cnt; // 설치된 공유기의 수 +} + +// 최소 인접 거리 중 최댓값 구하기 +int binarySearch(int left, int right, int target, vector& router) { + while (left <= right) { + // 가장 인접한 두 공유기 사이의 거리가 mid일 때, 설치할 수 있는 공유기 개수 + int mid = (left + right) / 2; + int installed = cntRouter(mid, router); + + if (installed >= target) { // mid의 거리로는 target 개수 이상의 공유기를 설치할 수 있음 -> 거리를 늘려보자 + left = mid + 1; + } + else { // mid의 거리로는 target만큼의 공유기 설치할 수 없음 -> 거리를 줄여야 한다 + right = mid - 1; + } + } + return left - 1; //upper bound값에서 1을 뺌 +} + +int main() { + int n, c; + + // 입력 + cin >> n >> c; + vector house(n, 0); + for (int i = 0; i < n; i++) { + cin >> house[i]; + } + + // 연산 + sort(house.begin(), house.end()); + + // 연산 & 출력 + // 최소 거리: 1 + // 최장 거리: 가장 멀리 떨어진 두 집 사이의 거리 + cout << binarySearch(1, house[n - 1] - house[0], c, house); + return 0; +} \ No newline at end of file diff --git "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\355\214\214\354\235\274\354\227\205\353\241\234\353\223\234\354\232\251" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\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/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\355\225\204\354\210\230/10815.cpp" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\355\225\204\354\210\230/10815.cpp" new file mode 100644 index 00000000..ecb19094 --- /dev/null +++ "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\355\225\204\354\210\230/10815.cpp" @@ -0,0 +1,46 @@ +#include +#include +#include + +using namespace std; + +/* +* 카드의 존재 여부만 판단하면 되므로, 이분 탐색을 이용해 해당 카드의 인덱스를 찾습니다. +*/ + +int binarySearch(int num, vector& card, int n) { + //카드 인덱스의 최소값: 0, 최대값: n + int left = 0; int right = n; + while (left <= right) { + int mid = (left + right) / 2; + if (num == card[mid]) { + return 1; + } + if (num > card[mid]) { + left = mid + 1; + } + else right = mid - 1; + } + return 0; +} + + +int main() { + ios_base::sync_with_stdio(0); + cin.tie(0); cout.tie(0); + // 입력 + int n, m, num; + cin >> n; + vector card(n); + for (int i = 0; i < n; i++) { + cin >> card[i]; + } + sort(card.begin(), card.end()); // 이분 탐색을 위해 정렬 + + cin >> m; + while (m--) { + cin >> num; + // 연산 & 출력 + cout << binarySearch(num, card, n) << ' '; + } +} \ No newline at end of file diff --git "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\355\225\204\354\210\230/14500.cpp" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\355\225\204\354\210\230/14500.cpp" new file mode 100644 index 00000000..f0ed47ec --- /dev/null +++ "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\355\225\204\354\210\230/14500.cpp" @@ -0,0 +1,85 @@ +#include +#include +#include + +using namespace std; + +vector>board; + +int ans; + +void dfs(int x, int y, int depth, int sum) { + + vector dx = { -1,0,1,0 }; + vector dy = { 0,1,0,-1 }; + + if (depth == 4) { // 칸 4개 선택했으면 ans 최대값 갱신 + ans = max(ans, sum); + return; + } + + // 아래 코드가 들어가면 가지치기가 돼 백트래킹이 돼요! + //if (ans >= MAX * (4 - cnt) + sum) { + // return; + //} + + for (int i = 0; i < 4; i++) { + // 선택할 칸 + int nx = x + dx[i]; + int ny = y + dy[i]; + + if (nx < 0 || nx >= board.size() || ny < 0 || ny >= board[0].size() || !board[nx][ny]) { // 범위를 벗어났거나 이미 방문한 블록이라면 넘어가기 + continue; + } + + int temp = board[nx][ny]; // 방문 처리하기 전 해당 칸 가치 저장 + board[nx][ny] = 0; // 방문 처리 : 4개를 선택함에 있어서 똑같은 블록을 선택하지 않기 위해 + + // 다음 탐색 -> depth 1 증가 && sum값에 현재 칸 가치 더하기 + if (depth == 2) { // ㅜ 모양은 현재 위치에서 다시 탐색! + dfs(x, y, depth + 1, sum + temp); + } + dfs(nx, ny, depth + 1, sum + temp); // 선택한 칸으로 이동 + + board[nx][ny] = temp; // 이후의 케이스에서 재방문할 수 있으므로 원래대로 돌려줌 + + } +} + +/* +* HINT : 하나의 도형은 무언가 특별한 것 같아요! or 테트로미노의 모양은 탐색의 관점에서 특징이 있는 것 같아요! +* 1. ㅜ 모양을 제외한 테트로미노의 모양은 깊이가 4인 dfs의 탐색 모양 +* -> dfs로 블록을 하나씩 선택해가면서 개수(cnt)와 합(sum)을 계산 +* -> 4개 선택하면 최댓값 갱신 +* 2. 예외 : ㅜ 모양은 블록을 2개 선택했을 때 현재 블록에서 다시 블록을 선택해준다. +*/ + + +int main() { + + // 입력 + int n, m; + cin >> n >> m; + board.assign(n, vector(m, 0)); + + + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + cin >> board[i][j]; + } + } + + // 연산 + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + int temp = board[i][j]; + board[i][j] = 0; + dfs(i, j, 1, temp); + board[i][j] = temp; + } + } + + // 출력 + cout << ans; + return 0; +} \ No newline at end of file diff --git "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\355\225\204\354\210\230/16401.cpp" "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\355\225\204\354\210\230/16401.cpp" new file mode 100644 index 00000000..6002a61d --- /dev/null +++ "b/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\355\225\204\354\210\230/16401.cpp" @@ -0,0 +1,47 @@ +#include +#include + +using namespace std; + +/* +* 이분 탐색을 이용하여 나눠줄 수 있는 최대한 긴 과자의 길이를 찾아낸다. +*/ + +#define MAX_COOKIE 1000000000 + +int binarySearch(int m, vector &cookie) { + int right = MAX_COOKIE; // 과자의 최대 길이: 1000000000 + int left = 1; // 과자의 최소 길이: 1 + int res=0; + + while (left <= right) { + int mid = (left + right) / 2; + int cnt = 0; + // mid 길이만큼씩 나눠주면 몇 명에게 나눠줄 수 있는지 세기 + for (int i = 0; i < cookie.size(); i++) { + cnt += cookie[i] / mid; + } + if (cnt >= m) { + left = mid + 1; + res = mid; + } + else{ + right = mid - 1; + } + } + return res; +} + +int main() { + int m, n; + // 조카 수, 과자 수 입력 + cin >> m >> n; + vector cookie(n); + // 막대과자 길이 입력 + for (int i = 0; i < n; i++) { + cin >> cookie[i]; + } + // 연산 & 출력 + cout << binarySearch(m, cookie); + return 0; +} \ No newline at end of file diff --git "a/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\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/10_\354\235\264\353\266\204 \355\203\220\354\203\211/\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/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 e69de29b..9d54f6c2 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" @@ -0,0 +1,76 @@ +# 투 포인터 (Two Pointer) + +[메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4) + +## 💻 튜터링 + +### 라이브 코딩 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :----------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :----------: | :--------: | +| 11659 | 구간 합 구하기4 | | [바로가기](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%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/11659.cpp) | 누적 합 | +| 21921 | 블로그 | | [바로가기](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%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/21921.cpp) | 누적 합, 슬라이딩 윈도우 | +| 2470 | 두 용액 | | [바로가기](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%9D%BC%EC%9D%B4%EB%B8%8C%20%EC%BD%94%EB%94%A9/2470.cpp) | 투 포인터 | + +## ✏️ 과제 + +### 마감기한 + +~ 5 / 16 (화) 18:59 - 과제 제출
+~ 5 / 18 (목) 23:59 - 추가 제출
+ +### 필수 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :-----------------------------------------------------------------------: | :------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :------------------------: | +| 14503 | 로봇 청소기 | | [C++]() | 구현, 시뮬레이션 | +| 20922 | 겹치는 건 싫어 | | [C++]() | 투 포인터 | +| 20437 | 문자열 게임 2 | | [C++]() | 슬라이딩 윈도우 | + +### 도전 + +| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 | +| :--------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :--: | +| 13422 | 도둑 | | [C++]() | 투 포인터, 슬라이딩 윈도우 | +| 2473 | 세 용액 | | [C++]() | 투 포인터 | +--- + +### 힌트 + +
+로봇 청소기 +
+    청소할 공간이 없을 때까지 계속해서 청소하는 방식이네요. 배웠던 알고리즘과 비슷해보이지 않나요? 방향에 유의하여 풀어보아요. +
+
+ +
+겹치는 건 싫어 +
+    두 포인터를 맨 왼쪽에 두고 오른쪽에 있는 숫자를 현재 수열에 추가할 수 있을지 없을지를 생각하며 탐색해볼까요? +
+
+ +
+문자열 게임 2 +
+    특정 문자가 k개 포함되면서 양쪽 끝이 해당 문자로 같아야 한다고 하니 우리에게 필요한 건 각 문자의 위치겠네요! 슬라이딩 윈도우를 사용해서 풀이해줘야 할 것 같은데, 윈도우의 크기는 얼마여야 할까요? +
+
+ +
+도둑 +
+    마을이 원이라는 점에 주의하여 슬라이딩 윈도우로 훔칠 수 있는 돈을 계산해봅시다. +
+
+ +
+세 용액 +
+    라이브코딩에서 다뤘던 두 용액 문제에 용액 하나가 추가됐네요! 포인터 3개를 쓰기는 힘들 것 같으니 결국 투포인터를 사용해 풀이해줘야 하는데, 나머지 하나는 어떻게 하면 좋을까요? 한 용액이 반드시 포함되도록 하고 나머지 두 용액을 찾아주면 좋을 것 같네요. +
+
+ + +--- diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\352\260\225\354\235\230 \354\236\220\353\243\214/11_\355\210\254\355\217\254\354\235\270\355\204\260_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\352\260\225\354\235\230 \354\236\220\353\243\214/11_\355\210\254\355\217\254\354\235\270\355\204\260_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" new file mode 100644 index 00000000..793aa5cb Binary files /dev/null and "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\352\260\225\354\235\230 \354\236\220\353\243\214/11_\355\210\254\355\217\254\354\235\270\355\204\260_\353\254\270\354\240\234\355\225\264\354\204\244.pdf" differ diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\352\260\225\354\235\230 \354\236\220\353\243\214/11_\355\210\254\355\217\254\354\235\270\355\204\260_\354\235\264\353\241\240.pdf" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\352\260\225\354\235\230 \354\236\220\353\243\214/11_\355\210\254\355\217\254\354\235\270\355\204\260_\354\235\264\353\241\240.pdf" new file mode 100644 index 00000000..dfd988c8 Binary files /dev/null and "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\352\260\225\354\235\230 \354\236\220\353\243\214/11_\355\210\254\355\217\254\354\235\270\355\204\260_\354\235\264\353\241\240.pdf" differ diff --git "a/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\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/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\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/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11659.cpp" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11659.cpp" new file mode 100644 index 00000000..974b8edb --- /dev/null +++ "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/11659.cpp" @@ -0,0 +1,43 @@ +#include +#include + +using namespace std; + +/* 누적 합 계산하기 */ +void calSum(int n, vector &sum) { + for (int i = 1; i <= n; i++) { + sum[i] += sum[i - 1]; // 첫번째 수부터 i번째 수까지의 누적 합 + } +} + +/* i번째 수부터 j번째 수까지의 합 계산하기 */ +int getPrefixSum(int i, int j, vector &sum) { + return sum[j] - sum[i - 1]; +} + +int main() { + // 입출력 성능 향상 + ios_base::sync_with_stdio(false); + cin.tie(NULL); + cout.tie(NULL); + + int n, m, i, j; + vector sum; + + // 입력 + cin >> n >> m; + sum.assign(n + 1, 0); // sum[0]을 0으로 설정 -> i-1이 0인 경우 따로 분리하지 않아도 됨 + for(int i = 1; i <= n; i++) { + cin >> sum[i]; + } + + // 연산 + calSum(n, sum); + + while (m--) { + cin >> i >> j; + // 출력 + cout << getPrefixSum(i, j, sum) << "\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\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/21921.cpp" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/21921.cpp" new file mode 100644 index 00000000..dfe87330 --- /dev/null +++ "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/21921.cpp" @@ -0,0 +1,77 @@ +#include +#include + +using namespace std; +typedef pair ci; + +//슬라이딩 윈도우로 최대 방문자 수(ans)와 그 기간의 개수를 pair로 리턴 +ci slidingWindow(vector &count, int n, int x) { + // 윈도우 초기화 + int left = 1, right = x; + int visitor = 0; // 방문자 수 + int cnt = 1; // 최대 방문자 수 기간 개수 + + for (int i = left; i <= right; i++) { + visitor += count[i]; + } + int max_visitor = visitor; // 최대 방문자 수 + + while (right < n) { + visitor -= count[left++]; // 이번 윈도우에서 제외 + visitor += count[++right]; // 이번 윈도우에서 추가 + + if (visitor > max_visitor) { // 현재 방문자 수(section_visitor)가 최대 방문자 수(ans)보다 크다면 + max_visitor = visitor; // 최대 방문자 수(ans) 갱신 + cnt = 1; // 최대 방문자 수 기간 개수 초기화 + } + else if (visitor == max_visitor) { // 현재 방문자 수(section_visitor)가 최대 방문자 수(ans)와 같다면 + cnt++; // 최대 방문자 수 기간 개수 1 추가 + } + } + return {max_visitor, cnt}; +} + +ci prefixSum(vector &count, int n, int x) { + int max_visitor = 0, cnt = 0; + vector sum(n + 1, 0); // i번째 일까지의 방문자 수 누적합 저장하는 배열 + for(int i = 1; i <= n; i++) { + sum[i] = sum[i - 1] + count[i]; + } + + for(int i = x; i <= n; i++) { + int visitor = sum[i] - sum[i - x]; // i-x부터 x일간 방문자 수 + if (visitor > max_visitor) { // 최대 방문자 수 갱신 + max_visitor = visitor; + cnt = 1; + } + else if (visitor == max_visitor) { // 최대 방문자 수가 같은 경우 기간 개수 갱신 + cnt++; + } + } + return {max_visitor, cnt}; +} + +int main() { + int x, n; + vector count; + + // 입력 + cin >> n >> x; + count.assign(n + 1, 0); + for (int i = 1; i <= n; i++) { + cin >> count[i]; + } + + // 연산 + ci ans = slidingWindow(count, n, x); + // ci ans = prefixSum(count, n, x); + + // 출력 + if (ans.first == 0) { // 최대 방문자 수가 0이면 + cout << "SAD"; + } else { + cout << ans.first << "\n" << ans.second; + } + + 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\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2470.cpp" "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2470.cpp" new file mode 100644 index 00000000..a04b4027 --- /dev/null +++ "b/11_\355\210\254 \355\217\254\354\235\270\355\204\260/\353\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/2470.cpp" @@ -0,0 +1,50 @@ +#include +#include +#include //abs() +#include //sort() + +using namespace std; +typedef pair ci; + +/* 투 포인로 두 용액의 합이 가장 0에 가까운 용액 쌍 리턴 */ +ci mixLiquid(vector &liquid, int left, int right){ + int min_value = abs(liquid[left] + liquid[right]); // 두 용액의 합의 값 중 가장 가까운 값 + ci ans = {liquid[left], liquid[right]}; // 합이 가장 0에 가까운 두 용액의 특성값 + + // left는 항상 right보다 작아야 함 + while (left < right) { + int value = liquid[left] + liquid[right]; // 두 용액 혼합 + if(abs(value) < min_value) { // 현재 합이 min_value보다 더 0에 가까우면 + min_value = abs(value); // min_value 갱신 + ans = {liquid[left], liquid[right]}; // ans 갱신 + } + if (value < 0) { // 현재 값이 0보다 작다면 더 큰 값을 만들어야 함 -> lef++ + left++; + } else if (value > 0) { // 현재 값이 0보다 크다면 더 작은 값을 만들어야 함 -> right-- + right--; + } else { // 현재 값이 0이면 이보다 더 0보다 가까운 값은 존재하지 않으므로 탐색 종료 + break; + } + } + return ans; +} + +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()); + ci ans = mixLiquid(liquid, 0, n - 1); + + // 출력 + cout << ans.first << " " << ans.second; + 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\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\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\235\274\354\235\264\353\270\214 \354\275\224\353\224\251/\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.cpp" "b/12_\355\212\270\353\246\254/\355\225\204\354\210\230/15681.cpp" new file mode 100644 index 00000000..7f011a16 --- /dev/null +++ "b/12_\355\212\270\353\246\254/\355\225\204\354\210\230/15681.cpp" @@ -0,0 +1,59 @@ +#include +#include +#include//? + +using namespace std; + +/* + * 트리의 정점의 수 구하기 응용 문제 + * + * 1. 루트에서 DFS를 사용하여 탐색 + * 2. 각 노드를 루트로 하는 서브트리의 정점 수를 재귀적으로 벡터에 저장 + * - 서브트리에 속한 정점의 개수를 저장하는 dp 배열을 1로 초기화 + * - 탐색 시 현재 정점의 자식 노드만 탐색해서 현재 정점의 dp 값에 더해줌 + * 3. 쿼리로 주어지는 정점의 서브트리의 정점의 개수를 dp에서 찾아서 출력 + */ + +void dfs(int cur, int prev, vector>& tree, vector& dp) {//cur: root, prev: 재귀 전 루트. + + for (int i = 0; i < tree[cur].size(); i++) { // 현재 정점의 "자식 노드" 탐색 + if (tree[cur][i] == prev) {//중력없는 트리다보니까(루트없는)->자식이었던 애가 부모이기도 한 상황 발생. 그래서 그런 상황 continue + continue;//다시 for문 + } + dfs(tree[cur][i], cur, tree, dp);//지금의 cur가 재귀타고 내려가면 prev가 됨. 또 그 노드(지금 시점 자식인 애)의 깊이를 본다. + dp[cur] += dp[tree[cur][i]]; // 자식 노드의 dp값 더해주기(dp값: 서브트리 정점갯수. 본인포함) + } + + return;//깊이 다 재면 리턴 +} + +int main() { + //속도향상 + ios::sync_with_stdio(false); + cin.tie(0); + cout.tie(0); + + // 입력 + int n, r, q, u, v;//n: 트리 정점의 수, r: 루트 번호, 쿼리수: q + cin >> n >> r >> q;//트리 정점의 수, 루트의 번호, 쿼리의 수 + + + vector>tree(n + 1, vector(0));//트리. 이차배열(행: 해당 노드의 번호. 열: 해당 노드의 자식들) + + for (int i = 0; i < n - 1; i++) {//n-1줄에 걸쳐(문제에서 일케말함. 간선이니까 그런듯) + cin >> u >> v;//u v형태로 트리에 속한 간선의 정보가 주어진다. + tree[u].push_back(v);//트리에 넣는다. u와 연결된 v라는 뜻. 따라서 u인덱스에 v를 넣는다. + tree[v].push_back(u);//트리에 넣는다. + } + + // 연산 + //dp는 서브트리의 노드의 갯수를 저장하는 배열이다. + vectordp(n + 1, 1); // 자신도 자신을 루트로 하는 서브트리에 포함되므로 0이 아닌 1로 dp 초기값 설정 + dfs(r, 0, tree, dp);//깊이탐색. r: 루트번호 + + // 출력 + while (q--) {//q: 해당 수만큼 답하라했음 + cin >> u;//해당 정점의 서브트리 수를 묻는 것임 + cout << dp[u] << '\n';//해당 정점의 서브트리 수 뱉음 + } +} \ No newline at end of file diff --git "a/12_\355\212\270\353\246\254/\355\225\204\354\210\230/3190.cpp" "b/12_\355\212\270\353\246\254/\355\225\204\354\210\230/3190.cpp" new file mode 100644 index 00000000..3d5c1b7e --- /dev/null +++ "b/12_\355\212\270\353\246\254/\355\225\204\354\210\230/3190.cpp" @@ -0,0 +1,93 @@ +#include +#include +#include + +using namespace std; + +// 뱀의 이동 방향 +const int dx[] = {0, 1, 0, -1}; // 동, 남, 서, 북 +const int dy[] = {1, 0, -1, 0}; + +int main() { + int n; + cin >> n; + + // 게임판 초기화 + vector> board(n, vector(n, 0)); + + int k; + cin >> k; + + // 사과 위치 설정 + for (int i = 0; i < k; i++) { + int row, col; + cin >> row >> col; + board[row - 1][col - 1] = 1; // 사과는 1로 표시 + } + + int l; + cin >> l; + + // 방향 변환 정보 저장 + queue> directions; + for (int i = 0; i < l; i++) { + int x; + char c; + cin >> x >> c; + directions.push({x, c}); + } + + int dir = 0; // 뱀의 초기 이동 방향 (동쪽) + int time = 0; // 현재 시간 + int x = 0, y = 0; // 뱀의 머리 위치 + + // 뱀의 이동 경로를 저장하는 큐 + queue> snake; + snake.push({x, y}); + board[x][y] = 2; // 뱀은 2로 표시 + + while (true) { + // 시간이 경과하면 방향 변환 + if (!directions.empty() && directions.front().first == time) { + char turn = directions.front().second; + directions.pop(); + + if (turn == 'L') { + dir = (dir + 3) % 4; // 왼쪽으로 90도 회전 + } else if (turn == 'D') { + dir = (dir + 1) % 4; // 오른쪽으로 90도 회전 + } + } + + // 다음 칸으로 이동 + int nx = x + dx[dir]; + int ny = y + dy[dir]; + + // 게임 종료 조건 검사 + if (nx < 0 || nx >= n || ny < 0 || ny >= n || board[nx][ny] == 2) { + cout << time + 1 << '\n'; // 1부터 시작하므로 +1 + break; + } + + // 이동한 칸에 사과가 없으면 꼬리 제거 + if (board[nx][ny] == 0) { + int tailX = snake.front().first; + int tailY = snake.front().second; + snake.pop(); + board[tailX][tailY] = 0; + } + + // 뱀 이동 + snake.push({nx, ny}); + board[nx][ny] = 2; + + // 다음 위치로 머리 갱신 + x = nx; + y = ny; + + // 시간 증가 + time++; + } + + return 0; +} 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..98aafcea --- /dev/null +++ "b/12_\355\212\270\353\246\254/\355\225\204\354\210\230/5639.cpp" @@ -0,0 +1,38 @@ +#include +using namespace std; + +struct Node { + int data; + Node* left;//연결되어야 하니까 포인터 + Node* right; +}; + +Node* insert(Node* node, int data) { + if (node == NULL) {//타고타고 비어있을 때만 새로생성 + node = new Node(); + node->data = data; + node->left = node->right = NULL; + } + else if (data <= node->data) + node->left = insert(node->left, data); + else + node->right = insert(node->right, data); + return node; +} + +void postorder(Node* node) { + if (node == NULL) return; + postorder(node->left); + postorder(node->right); + cout << node->data << '\n'; +} + +int main() { + ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); + Node* root = NULL;//포인터: 연결위해 + int x; + while (cin >> x) {//입력받고 + root = insert(root, x);//insert + } + postorder(root);//루트노드만 알면 된다. +} diff --git a/README.md b/README.md index 0846e3b6..dbf4b4d4 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,15 @@ SW학부 원스탑 튜터링에서 진행하는 코딩 테스트 대비 알고 | 2023.02.14 | OT | [@dooli1971039](https://github.com/dooli1971039) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/00_OT/00.%20OT%20%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C.pdf) | - | 녹화 영상 제공 | | 2023.02.17 | 정렬, 맵, 셋 | [@jk0527](https://github.com/jk0527) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/01_%EC%A0%95%EB%A0%AC%2C%20%EB%A7%B5%2C%20%EC%85%8B/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C/01_%EC%A0%95%EB%A0%AC%2C_%EB%A7%B5%2C_%EC%85%8B_%EC%9D%B4%EB%A1%A0.pdf) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/01_%EC%A0%95%EB%A0%AC%2C%20%EB%A7%B5%2C%20%EC%85%8B) | - | | 2023.02.24 | 스택, 큐, 덱 | [@kimyu0218](https://github.com/kimyu0218) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/02_%EC%8A%A4%ED%83%9D%2C%20%ED%81%90%2C%20%EB%8D%B1/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C/02_%EC%8A%A4%ED%83%9D%2C_%ED%81%90%2C_%EB%8D%B1_%EC%9D%B4%EB%A1%A0.pdf) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/02_%EC%8A%A4%ED%83%9D%2C%20%ED%81%90%2C%20%EB%8D%B1) | - | -| 2023.03.03 | 정수론 | [@kwakrhkr59](https://github.com/kwakrhkr59) | [바로가기]() | [바로가기]() | - | -| 2023.03.10 | 브루트 포스 | [@Dong-droid](https://github.com/Dong-droid) | [바로가기]() | [바로가기]() | - | -| 2023.03.17 | 우선순위 큐 | [@dbswn](https://github.com/dbswn) | [바로가기]() | [바로가기]() | - | -| 2023.03.24 | 그리디 알고리즘 | [@grdnr13](https://github.com/grdnr13) | [바로가기]() | [바로가기]() | - | -| 2023.03.31 | DFS & BFS | [@kimyu0218](https://github.com/kimyu0218) | [바로가기]() | [바로가기]() | - | -| 2023.04.07 | 백트래킹 | [@sujeong000](https://github.com/sujeong000) | [바로가기]() | [바로가기]() | - | -| 2023.04.14 | 동적 계획법 | [@sujeong000](https://github.com/sujeong000) | [바로가기]() | [바로가기]() | - | -| 2023.05.05 | 이분 탐색 | [@grdnr13](https://github.com/grdnr13) | [바로가기]() | [바로가기]() | 녹화 강의 제공 | -| 2023.05.12 | 투 포인터 | [@kwakrhkr59](https://github.com/kwakrhkr59) | [바로가기]() | [바로가기]() | - | +| 2023.03.03 | 정수론 | [@kwakrhkr59](https://github.com/kwakrhkr59) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/03_%EC%A0%95%EC%88%98%EB%A1%A0/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C/03_%EC%A0%95%EC%88%98%EB%A1%A0_%EC%9D%B4%EB%A1%A0.pdf) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/03_%EC%A0%95%EC%88%98%EB%A1%A0) | - | +| 2023.03.10 | 브루트 포스 | [@Dong-droid](https://github.com/Dong-droid) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/04_%EB%B8%8C%EB%A3%A8%ED%8A%B8%20%ED%8F%AC%EC%8A%A4/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C/04_%EB%B8%8C%EB%A3%A8%ED%8A%B8%ED%8F%AC%EC%8A%A4_%EC%9D%B4%EB%A1%A0.pdf) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/04_%EB%B8%8C%EB%A3%A8%ED%8A%B8%20%ED%8F%AC%EC%8A%A4) | - | +| 2023.03.17 | 우선순위 큐 | [@dbswn](https://github.com/dbswn) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/05_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%20%ED%81%90/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C/05_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%ED%81%90_%EC%9D%B4%EB%A1%A0.pdf) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/05_%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%20%ED%81%90) | - | +| 2023.03.24 | 그리디 알고리즘 | [@grdnr13](https://github.com/grdnr13) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/06_%EA%B7%B8%EB%A6%AC%EB%94%94%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C/06_%EA%B7%B8%EB%A6%AC%EB%94%94%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98_%EC%9D%B4%EB%A1%A0.pdf) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/06_%EA%B7%B8%EB%A6%AC%EB%94%94%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98) | - | +| 2023.03.31 | DFS & BFS | [@kimyu0218](https://github.com/kimyu0218) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/07_DFS%20%26%20BFS/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C/07_DFS%26BFS_%EC%9D%B4%EB%A1%A0.pdf) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/07_DFS%20%26%20BFS) | - | +| 2023.04.07 | 백트래킹 | [@sujeong000](https://github.com/sujeong000) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/08_%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9/%EA%B0%95%EC%9D%98%20%EC%9E%90%EB%A3%8C/08_%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9_%EC%9D%B4%EB%A1%A0.pdf) | [바로가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/tree/main/08_%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9) | - | +| 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.26 | 최단 경로 | [@Dong-droid](https://github.com/Dong-droid) | [바로가기]() | [바로가기]() | - | | 2023.06.02 | 유니온 파인드 | [@bsa0322](https://github.com/bsa0322) | [바로가기]() | [바로가기]() | 2기 자료 제공 |