※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 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

+ Recent posts