1450 : 냅색문제

풀이

숫자의 크기가 너무 커서 일반적인 냅색 풀이로는 풀 수 없다.

그렇다고 2^30을 돌리자니 그것도 크기가 너무 크다.

수열을 정렬하고 반으로 나눠서 절반씩 완전탐색 해주자.

2^15씩 두 번이니 충분히 돌고도 남는다.

그리고 완전탐색한 두 조합을 linear하게 잘 섞어주자.

코드

#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;

int n, c, ans, a[33];
vector<int> v1, v2;

void dfs(int s, int e, int sum, vector<int>& v) {
	if (sum > c) return;
	if (s > e) return v.push_back(sum);
	dfs(s + 1, e, sum, v);
	dfs(s + 1, e, sum + a[s], v);
}

int main() {
	scanf("%d %d", &n, &c);
	for (int i = 0; i < n; i++) scanf("%d", &a[i]);

	dfs(0, n / 2 - 1, 0, v1); sort(v1.begin(), v1.end());
	dfs(n / 2, n - 1, 0, v2); sort(v2.begin(), v2.end());
	
	int e = v2.size() - 1;
	for (int s = 0; s < v1.size(); s++) {
		while (e >= 0 && v1[s] + v2[e] > c) e--;
		ans += e + 1;
	}
	printf("%d", ans);

	return 0;
}

아무말

백준, 백준 온라인 저지, BOJ, Baekjoon Online Judge, C, C++, 씨, 씨쁠쁠, JAVA, algorithm, 자바, 알고리즘, 자료구조, 문제, 문제 풀이, 풀이

wookje.kwon's profile image

wookje.kwon

2017-11-02 13:21

Read more posts by this author