백준 2869 달팽이는 올라가고 싶다(이분탐색)

달팽이는 올라가고 싶다

A,B,V 제한을 보면 10억이다. 보기엔 간단히 더해서 풀면 풀릴거같은 문제지만, 그렇게 풀면 O(N)이 되어 시간초과가 된다.

더 적은 시간으로 풀어야 하는데, 이 문제는 두가지 문제풀이가 존재한다.

수학으로 접근하는 방법 O(1) 과 이분탐색으로 접근하는 방법 O(logN) 이다.

나는 이분탐색을 이용해서 풀었고, 수학으로 접근하는 방법을 보고싶다면 다른 블로그를 참고하길 바란다.

주의해야할 점 이분탐색에 대한 개념을 인지하고 있다는 전제 하에 해설합니다! 이분탐색에 대한 개념을 한번 보고 오시면 도움이 많이 될 겁니다!

문제분석

1.낮에 a만큼 올라가고, 밤에 b만큼 내려간다.

  • 첫번째 날 +a-b, 두번째 날 +a-b, … , __내가 구하려는 날__에 +a(-b)를 하면 v가 넘는다.

    첫번째 날 두번째 날 ... 내가 구하려는 날의 전날 내가 구하려는 날
    X X X X O
  • 어떤 기준에 의해 Yes/No로 나누어지는 것이므로 이분탐색으로 풀 수 있다.

2.어떤 기준인가?

  • 기준은 어떤 x날의 전날까지 오른 길이 (x-1) * (a-b) 에 x날의 a를 더한 값 (x-1) * (a-b)+a 이 v보다 크면 뒤의 범위를 앞으로 당겨주면 되고, 작으면 범위를 뒤로 밀어주면 된다.

3.첫날과 마지막날의 범위는 어떻게 잡나?

  • 이분탐색에서 중요한 부분중 하나이다. 가능한 정답의 최솟값과 최댓값을 정해주어야 하는데, 이 문제에선 최솟값 : 첫번째 날(1) 이고, 최댓값: a<b이므로 무조건 하루에 하나는 올라간다. 즉 v가 최댓값이 된다.

소스

#include<iostream>
#include<algorithm>

using namespace std;

int main() {
	int a, b, v;
	cin >> a >> b >> v;
	long long last = v;
	long long first = 0;
	long long mid;
	long long ans;
	while (first <= last) {
		mid = (first + last) / 2;
		if (v <= (mid-1)*(a-b)+a)
		{
			last=mid-1;
			ans = mid;
		}
		else {
			first=mid+1;
		}
	}
	cout << ans;
}

댓글남기기