Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[최단 경로] 2171064 문하영 #354

Open
wants to merge 37 commits into
base: 2171064-문하영2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
93c419c
[5월 5일] 이분 탐색 리드미 업로드
jk0527 May 5, 2023
88830b6
[5월 5일] 이분 탐색 강의 자료 업로드
jk0527 May 5, 2023
5a6372c
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 5, 2023
ad6eebb
[5월 5일] 이분 탐색 라이브 코딩 코드 업로드
jk0527 May 5, 2023
9f9b791
[5월 5일] 이분 탐색 리드미 수정
jk0527 May 5, 2023
3a55ea1
[5월 5일] 리드미 수정
jk0527 May 5, 2023
cedeb06
[5월 9일] 이분 탐색 과제 코드 업로드
jk0527 May 9, 2023
7699152
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 9, 2023
bbfbc93
[5월 9일] 투 포인터 리드미 업로드
jk0527 May 9, 2023
7baa1de
[5월 10일] 이분 탐색 리드미 수정
jk0527 May 10, 2023
b6f7843
[5월 10일] 투 포인터 강의 자료 업로드
jk0527 May 10, 2023
b92e936
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 10, 2023
56d70ae
[5월 10일] 리드미 수정
jk0527 May 10, 2023
ae608f8
[5월 12일] 투 포인터 라이브 코딩 코드 업로드
jk0527 May 12, 2023
725af3e
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 12, 2023
6846e9e
[5월 12일] 투 포인터 라이브 코딩 코드 업로드
jk0527 May 12, 2023
157d1fc
[5월 12일] 투 포인터 리드미 수정
jk0527 May 12, 2023
077bd1b
[5월 16일] 투 포인터 과제 코드 업로드
jk0527 May 16, 2023
b48257f
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 16, 2023
198416c
[5월 16일] 투 포인터 리드미 수정
jk0527 May 16, 2023
5536b51
[5월 16일] 트리 강의 자료 업로드
jk0527 May 16, 2023
9bf8964
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 16, 2023
cd29d82
[5월 16일] 트리 리드미 업로드
jk0527 May 16, 2023
f5fd534
[5월 16일] 리드미 수정
jk0527 May 16, 2023
5c5694a
[5월 19일] 트리 라이브 코딩 코드 업로드
jk0527 May 19, 2023
cf31227
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 19, 2023
a8cc122
[5월 19일] 트리 리드미 수정
jk0527 May 19, 2023
5ab3590
[5월 23일] 트리 과제 코드 업로드
jk0527 May 23, 2023
20be664
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 23, 2023
dad8d2c
[5월 23일] 트리 리드미 수정
jk0527 May 23, 2023
1373cde
[5월 23일] 최단 경로 강의 자료 업로드
jk0527 May 23, 2023
6d1de48
Merge branch 'main' of https://github.com/Altu-Bitu-Official/Altu-Bitu-4
jk0527 May 23, 2023
b57dc56
[5월 23일] 최단 경로 리드미 업로드
jk0527 May 23, 2023
c908c33
[5월 23일] 리드미 수정
jk0527 May 23, 2023
3f999ab
[최단 경로] 0530
gkdudans May 30, 2023
e3b4bfe
[최단 경로] 추가제출
gkdudans Jun 2, 2023
fc1ce0a
Rename 15695.cpp to 15685.cpp
gkdudans Jun 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions 10_이분 탐색/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# 이분 탐색 (Binary Search)

[메인으로 돌아가기](https://github.com/Altu-Bitu-Official/Altu-Bitu-4)

## 💻 튜터링

### 라이브 코딩

| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 |
| :-----------------------------------------------------------------------: | :----------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :----------: | :--------: |
| <a href="https://www.acmicpc.net/problem/1920" target="_blank">1920</a> | <a href="https://www.acmicpc.net/problem/1920" target="_blank">수 찾기</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/7.svg"/> | [바로가기](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) | 이분탐색, 정렬 |
| <a href="https://www.acmicpc.net/problem/10816" target="_blank">10816</a> | <a href="https://www.acmicpc.net/problem/10816" target="_blank">숫자 카드 2</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/7.svg"/> | [바로가기](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) | 이분탐색, 정렬, 해시를 이용한 집합과 맵 |
| <a href="https://www.acmicpc.net/problem/2110" target="_blank">2110</a> | <a href="https://www.acmicpc.net/problem/2110" target="_blank">공유기 설치</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/12.svg"/> | [바로가기](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 - 과제 제출 </br>
~ 5 / 11 (목) 23:59 - 추가 제출 </br>

### 필수

| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 |
| :-----------------------------------------------------------------------: | :------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :------------------------: |
| <a href="https://www.acmicpc.net/problem/14500" target="_blank">14500</a> | <a href="https://www.acmicpc.net/problem/14500" target="_blank">테트로미노</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/12.svg"/> | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/10_%EC%9D%B4%EB%B6%84%20%ED%83%90%EC%83%89/%ED%95%84%EC%88%98/14500.cpp) | 구현, 브루트 포스 |
| <a href="https://www.acmicpc.net/problem/10815" target="_blank">10815</a> | <a href="https://www.acmicpc.net/problem/10815" target="_blank">숫자 카드</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/6.svg"/> | [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) | 자료구조, 정렬, 이분 탐색 |
| <a href="https://www.acmicpc.net/problem/16401" target="_blank">16401</a> | <a href="https://www.acmicpc.net/problem/16401" target="_blank">과자 나눠주기</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/9.svg"/> | [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) | 이분 탐색, 매개 변수 탐색 |

### 도전

| 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 | 분류 |
| :--------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: | :-------: | :--: |
| <a href="https://www.acmicpc.net/problem/2343" target="_blank">2343</a> | <a href="https://www.acmicpc.net/problem/2343" target="_blank">기타 레슨</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/10.svg"/> | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/10_%EC%9D%B4%EB%B6%84%20%ED%83%90%EC%83%89/%EB%8F%84%EC%A0%84/2343.cpp) | 이분 탐색, 매개 변수 탐색 |
| <a href="https://www.acmicpc.net/problem/3079" target="_blank">3079</a> | <a href="https://www.acmicpc.net/problem/3079" target="_blank">입국심사</a> | <img height="25px" width="25px" src="https://static.solved.ac/tier_small/11.svg"/> | [C++](https://github.com/Altu-Bitu-Official/Altu-Bitu-4/blob/main/10_%EC%9D%B4%EB%B6%84%20%ED%83%90%EC%83%89/%EB%8F%84%EC%A0%84/3079.cpp) | 이분 탐색, 매개 변수 탐색 |

---

### 힌트

<details>
<summary>테트로미노</summary>
<div markdown="1">
&nbsp;&nbsp;&nbsp;&nbsp;테트로미노의 모양은 탐색의 관점에서 특징이 있는 것 같아요!
</div>
</details>

<details>
<summary>숫자 카드</summary>
<div markdown="1">
&nbsp;&nbsp;&nbsp;&nbsp;라이브 코딩 문제를 복습하며 풀어봅시다. 찾아야 할 게 무엇일까요?
</div>
</details>

<details>
<summary>과자 나눠주기</summary>
<div markdown="1">
&nbsp;&nbsp;&nbsp;&nbsp;막대 과자는 길이와 상관없이 여러 조각으로 나눠질 수 있어요!
</div>
</details>

<details>
<summary>기타 레슨</summary>
<div markdown="1">
&nbsp;&nbsp;&nbsp;&nbsp;블루레이 크기의 범위는 무엇일까요?
</div>
</details>

<details>
<summary>입국심사</summary>
<div markdown="1">
&nbsp;&nbsp;&nbsp;&nbsp;라이브 코딩 때 풀어본 공유기 설치 문제와 유사해보이네요. 어떤 값을 기준으로 탐색하여 무엇을 비교해야 할지 생각해보세요 :)
자료형의 범위에 유의해주세요
</div>
</details>

---
Binary file not shown.
Binary file not shown.
Empty file.
50 changes: 50 additions & 0 deletions 10_이분 탐색/도전/2343.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

/*
* 적절한 블루레이의 크기를 매개변수 탐색을 이용해 찾습니다.
* 이 때, 각 블루레이의 크기는 최대 강의 길이(maxLen) 이상, 강의 길이의 합(sumLen) 이하임을 이용합니다.
*/

int findSize(int&left, int right, vector<int> 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<int> 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;
}
64 changes: 64 additions & 0 deletions 10_이분 탐색/도전/3079.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef long long ll;
const int MAX = 1e5;

/*
* 매개변수 탐색을 이용하여 입국 심사에 걸리는 시간을 계산합니다.
* 각 입국 심사에 걸리는 시간에 따라 심사가능한 인원을 계산한 후, 일행 인원과 비교해가며 진행합니다.
*/

ll paramSearch(ll &m, ll &n, vector<ll>& 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<ll> 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;
}
Empty file.
79 changes: 79 additions & 0 deletions 10_이분 탐색/라이브 코딩/10816.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;
/*
* lower bound, upper bound를 구한 뒤, 둘의 차이를 구해주면 됩니다.
*/

//lower bound
int lowerBound(int left, int right, int target, vector<int>& 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<int>& 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<int> 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;
}
51 changes: 51 additions & 0 deletions 10_이분 탐색/라이브 코딩/1920.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;
/*
* 이분탐색을 이용해 입력으로 주어진 키 값의 존재 여부를 구합니다
*/

int binarySearch(int n, int key, vector<int> &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<int> 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;
}
57 changes: 57 additions & 0 deletions 10_이분 탐색/라이브 코딩/2110.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

// 가장 인접한 두 공유기 사이의 거리가 dist가 되도록 공유기를 설치했을 때, 설치된 공유기 개수
int cntRouter(int dist, vector<int>& 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<int>& 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<int> 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;
}
Empty file.
Loading