※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 1450번 문제인 냅색문제이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/1450
1450번: 냅색문제
첫째 줄에 N과 C가 주어진다. N은 30보다 작거나 같은 자연수이고, C는 10^9보다 작거나 같은 음이아닌 정수이고. 둘째 줄에 물건의 무게가 주어진다. 무게도 10^9보다 작거나 같은 자연수이다.
www.acmicpc.net
살펴봐야하는 경우의 수는 2^30가지이다. 이 모든 경우를 다 살펴보는 것은 시간초과를 피할 수 없다.
수들을 반반씩 두 개의 집합으로 나누어 15개의 숫자의 합의 경우의 수를 각각 구해 정렬 후 투포인터를 이용하면 32768(=2^15)가지의 부분합들을 선형으로 탐색하면서 문제를 해결할 수 있다.
이와 같은 방식의 문제풀이 방식을 더 익혀보고 싶다면 (cp에서의) meet in the middle 알고리즘에 대하여 찾아보자.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
ll N, X, Y, C;
vector<ll> A, B;
ll arr[15];
ll total = 0;
void funcA(int idx) {
if (idx == X) A.emplace_back(total);
else {
funcA(idx + 1);
total += arr[idx];
funcA(idx + 1);
total -= arr[idx];
}
}
void funcB(int idx) {
if (idx == Y) B.emplace_back(total);
else {
funcB(idx + 1);
total += arr[idx];
funcB(idx + 1);
total -= arr[idx];
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N >> C;
if (N == 1) {
ll x; cin >> x;
if (x <= C) cout << 2;
else cout << 1;
return 0;
}
X = N / 2; Y = N - X;
for (int i = 0; i < X; i++) cin >> arr[i];
funcA(0);
for (int i = 0; i < Y; i++) cin >> arr[i];
funcB(0);
sort(A.begin(), A.end());
sort(B.begin(), B.end());
ll ans = 0;
ll Asize = A.size(), Bsize = B.size();
ll cnt = Bsize;
ll idx = Bsize - 1;
for (int k = 0; k < Asize; k++) {
while (idx >= 0) {
if (A[k] + B[idx] > C) {
cnt--;
idx--;
}
else break;
}
ans += cnt;
}
cout << ans << '\n';
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 2110 // C++] 공유기 설치 (0) | 2021.11.01 |
---|---|
[BOJ 2819 // C++] 상근이의 로봇 (0) | 2021.10.31 |
[BOJ 1563 // C++] 개근상 (0) | 2021.10.29 |
[BOJ 3948 // C++] 홍준이의 친위대 (0) | 2021.10.28 |
[BOJ 8907 // C++] 네온 사인 (0) | 2021.10.27 |