반응형
250x250
Notice
Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 유니온 파인드
- ssafy 7기
- SSAFYcial
- 프로그래머스
- 이코테
- 싸피 7기 입학식
- bfs
- ssafy 7기 교수님
- React
- 웹 표준 사이트 만들기
- 프로그래머스 고득점 kit
- 백준
- 코딩교육
- Learning
- 코딩 교육
- SSAFY 입학식
- SSAFY
- 백준7576 bfs
- DenseNet
- dfs
- git
- ssafy 7기 합격
- 삼성청년sw아카데미
- 알고리즘
- SWEA
- pytorch
- SSAFY 8기
- 전이학습
- DP
- 삼성 청년 SW 아카데미
Archives
- Today
- Total
개미의 개열시미 프로그래밍
[알고리즘] 백준 2110 공유기 설치 - 자바 본문
728x90
반응형
공유기 설치 풀이노트
스터디때 발표를 하기 위해 정리했던 내용을 그대로 올려본다. 발표때마다 느끼지만 왤케 더듬지..
문제 이해하기
가장 인접한 두 공유기 사이의 거리를 최대
→ "공유기 3개를 설치하는데 공유기 사이 거리를 크게”
정렬 된 집 좌표 : 1_2__4___ 8_ 9
1_ 2_______ 9 1 7 → 가장 인접한 두 공유기의 거리는 7이 아닌 1
1___ 4____ 8 3 4 → 가장 인접한 두 공유기의 거리는 4가 아닌 3
-
정렬하기
house = new int[N];
for(int i=0; i<N; i++) {
house[i] = sc.nextInt();
}
Arrays.sort(house); // 이분 탐색하려면 무조건~
-
기준점 정하기
// '거리' 가 기준!!!
int start = 1; //최소로 이동할 수 있는 거리는 1이겠지
int end = house[N-1] - house[0]; //최대로 이동할 수 있는 거리는 8!
-
이분탐색시작
while(start <= end) {
int houseCnt =0;
int mid = (start + end) /2; // 그럼 중간 값부터 탐색을 시작
**int installed = house[0]; // #1. 무조건 처음 집부터 해야함!**
houseCnt++;
for(int i=1; i<house.length; i++) {
**if(mid + installed <= house[i])** {//#2. 중간값 + 공유기설치한집의 좌표 보다 다음 집의 좌표가 크다면
installed = house[i];
houseCnt++;
}
}
if(houseCnt < C) { // 공유기를 다 설치 못했다. end 갱신해서 다시
end = mid-1;
}else { // 공유기 설치는 다했다. 그래도 중간값 올려서 start가 end보다 커질때까지 탐색해보기
start = mid+1;
result = mid; // 일단, 답을 담아두자
}
}
부분설명
int houseCnt =0;
int mid = (start + end) /2; // 그럼 중간 값부터 탐색을 시작
**int installed = house[0]; // #1. 무조건 처음 집부터 해야함!**
houseCnt++; // 공유기 한대 설치했으니까
1 2 4 → 1
1 2 8 → 1
1 2 9 → 1
1 4 8 → 3
1 4 9 → 3
1 8 9 → 1
2 4 8 → 2
2 4 9 → 2
2 8 9 → 1
4 8 9 → 1
- 모든 경우의 수를 나열해봤을 때 처음 시작은 무조건 1로 시작해야 답이 나온다. 2부터 시작하면 최댓값이 안나오는건 당연한 것 같다.
- 이렇게 나열해보니 조합으로 풀어볼 수 있지 않을까 싶어 코드를 작성해봤다.
조합으로도 풀 수 있을까?
import java.util.Arrays;
import java.util.Scanner;
public class BOJ_2110_공유기설치2 {
static int N, C, result;
static int[] array;
static int max = Integer.MIN_VALUE;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
N = sc.nextInt(); // 집
C = sc.nextInt(); // 공유기 수
array = new int[N];
for(int i=0; i<N; i++) {
array[i] = sc.nextInt();
}
Arrays.sort(array); // 이분 탐색하려면 무조건~
dfs(0, 0, "");
System.out.println(max);
}
static void dfs(int idx, int cnt, String str) {
if(cnt == C) {
// System.out.println(str);
int arrayMin = Integer.MAX_VALUE;
for(int i=0; i<str.length()-1; i++) {
int a = Math.abs(str.charAt(i) - str.charAt(i+1));
arrayMin = Math.min(arrayMin, a);
}
max = Math.max(max, arrayMin);
return;
}
if(idx>=N)
return;
dfs(idx+1, cnt+1, str + array[idx]);
dfs(idx+1, cnt, str);
}
}
답은 메모리초과가 되었다. 만약 이 문제를 보고 누군가는 조합이라고 생각되어 문제를 풀 수도 있을 것 같다.
그런 경우는 어떻게 시간복잡도를 생각해서 문제에 접근해야할지 스터디원에게 질문을 했었는데
- 문제 조건에 입력의 개수는 적은데 주어지는 수가 많은 경우 이분탐색을 의심해보기
- 구글에 조합계산기를 검색 후 직접 검색하보면서 시간복잡도를 따져보기
아직 시간복잡도를 계산하고 그 문제를 어떻게 풀어야할지는 아직은 감이 부족한 것 같아 앞으로 만나는 문제마다 고민을 해봐야 겠다.
#2. 반복문 설명
for(int i=1; i<house.length; i++) {
**if(mid + installed <= house[i])** {//#2. 중간값 + 공유기설치한집의 좌표 보다 다음 집의 좌표가 크다면
installed = house[i];
houseCnt++;
}
}
중간값 + 공유기설치한집의 좌표 보다 다음 집의 좌표가 크다면 installed값을 해당 좌표로 변경해주고 공유기를 설치했으니 hoseCnt를 올려준다.
#3. 마지막 조건문 설명
if(houseCnt < C) { // 공유기를 다 설치 못했다. end 갱신해서 다시
end = mid-1;
}else { // 공유기 설치는 다했다. 그래도 중간값 올려서 start가 end보다 커질때까지 탐색해보기
start = mid+1;
result = mid; // 일단, 답을 담아두자
}
중간값의 변화를 출력해보면 아래와 같다.
총 반복문은 3번을 돌며 mid값은 4 -> 2 -> 3 순으로 변경되며 탐색을 한다.
728x90
반응형
'알고리즘 > 이분탐색' 카테고리의 다른 글
[알고리즘] 백준1939 중량제한 - 파이썬 (0) | 2021.11.26 |
---|---|
[알고리즘] 백준1300 K번째 수 - 파이썬 (0) | 2021.08.22 |
[알고리즘] 백준2110 공유기 설치 - 파이썬 (0) | 2021.08.21 |
[알고리즘] 백준2805 나무자르기 - 파이썬 (0) | 2021.08.21 |
[알고리즘] 백준1634 랜선자르기 - 파이썬 (0) | 2021.08.20 |
Comments