문제
https://www.acmicpc.net/problem/1052
걸린 시간
- 실패
시간초과 풀이
C++
#include <bits/stdc++.h>
#define fastio ios::sync_with_stdio(0), cin.tie(0)
#define all(c) c.begin(), c.end()
#define INF 1e9
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int main(){
fastio;
int n, k;
cin >> n >> k;
for(int i = 0; i <= pow(2, 24)-n; i++){
int cnt = 0;
int rn = n+i;
for(int j = 24; j >= 0; j--){
int tmp = pow(2, j);
if(rn >= tmp){
rn -= tmp;
cnt++;
}
}
if(cnt <= k){
cout << i << "\n";
return 0;
}
}
cout << -1 << "\n";
return 0;
}
물병을 2의 거듭제곱 중 큰 순서대로 줄여 나가면 줄여진 물병의 최소 개수를 구할 수 있다는 규칙을 찾아냈다. 하지만 pow 함수의 복잡도가 O(n) 임을 생각하지 못했고, 최악의 경우 224 * 24 * 23 / 2 = 4,630,511,616
번 반복되어 시간초과가 발생했다.
옳은 풀이
C++
#include <bits/stdc++.h>
#define fastio ios::sync_with_stdio(0), cin.tie(0)
#define all(c) c.begin(), c.end()
#define INF 1e9
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int main(){
fastio;
int n, k;
cin >> n >> k;
vector<int> p;
for(int i = 24; i >= 0; i--) p.push_back(pow(2, i));
for(int i = 0; i <= pow(2, 24)-n; i++){
int cnt = 0;
int rn = n+i;
for(int j = 0; j <= 24; j++){
int tmp = p[j];
if(rn >= tmp){
rn -= tmp;
cnt++;
}
}
if(cnt <= k){
cout << i << "\n";
return 0;
}
}
cout << -1 << "\n";
return 0;
}
0 부터 24 제곱까지의 계산이 중복되기 때문에 미리 구해놓은 후 사용하면, 줄일 수 있는 물병의 최소 개수를 상수 시간안에 구할 수 있어 224 * 24 = 402,653,184
로 통과할 수 있다.
C++
#include <bits/stdc++.h>
#define fastio ios::sync_with_stdio(0), cin.tie(0)
#define all(c) c.begin(), c.end()
#define INF 1e9
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int main(){
fastio;
int n, k;
cin >> n >> k;
for(int i = 0; i <= pow(2, 24)-n; i++){
int cnt = 0;
int rn = n+i;
while(rn > 0){
if(rn%2 == 1) cnt++;
rn /= 2;
}
if(cnt <= k){
cout << i << "\n";
return 0;
}
}
cout << -1 << "\n";
return 0;
}
다른 풀이로는 현재 값을 이분법으로 나누며 나머지가 1일 때, 즉 합쳐지지 못하는 물병의 개수가 발생할 때 마다 세어주는 방법이 있다.
검색을 해 보니 많은 사람들이 이 방법으로 문제를 해결했다. 하지만 개인적으론 처음 설명한 풀이 방법에 비해 직관적인 것 같지 않다.
'Baekjoon' 카테고리의 다른 글
Baekjoon 2615번 오목 (0) | 2021.05.16 |
---|---|
Baekjoon 1914번 하노이 탑 (0) | 2021.05.15 |
Baekjoon 2457번 공주님의 정원 (0) | 2021.05.04 |
Baekjoon 1629번 곱셈 (0) | 2021.04.25 |
Baekjoon 19948번 음유시인 영재 (0) | 2021.04.18 |
댓글