반응형
문제
세준이는 N개의 물건을 가지고 있고, 최대 C만큼의 무게를 넣을 수 있는 가방을 하나 가지고 있다.
N개의 물건을 가방에 넣는 방법의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N과 C가 주어진다. N은 30보다 작거나 같은 자연수이고, C는 10^9보다 작거나 같은 음이아닌 정수이고. 둘째 줄에 물건의 무게가 주어진다. 무게도 10^9보다 작거나 같은 자연수이다.
출력
첫째 줄에 가방에 넣는 방법의 수를 출력한다.
예제 입력 1
2 1
1 1
예제 출력 1
3
<코드>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
long long N,C,W[31],ans;
vector<long long> group1;
vector<long long> group2;
void dfs(int s, int e, vector<long long>& v, long long sum)
{
if(s > e)
{
v.push_back(sum);
return;
}
else
{
dfs(s+1, e, v, sum);
dfs(s+1, e, v, sum+W[s]);
}
}
int main()
{
cin >> N >> C;
for(int i = 0; i < N; i++)
{
cin >> W[i];
}
// 반으로 나눠서 경우의수 저장
dfs(0, N/2, group1, 0);
dfs(N/2 + 1, N-1, group2, 0);
sort(group2.begin(), group2.end());
for(int i = 0; i < group1.size(); i++)
{
ans += upper_bound(group2.begin(), group2.end(), C - group1[i]) - group2.begin();
}
cout << ans << endl;
}
풀이 방법
풀이법이 떠오르지 않아 wookje님 풀이를 참고하였습니다.
<기본 아이디어>
물건의 최대 개수가 30개이고 2의 30승의 경우 10억 7천만이므로 시간초과가 발생한다. 따라서 물건을 반으로 나누어 만들 수 있는 조합을 group1, group2 벡터에 각각 저장해놓는다. 그리고 group2 벡터만 정렬을 한 뒤 group1의 i번째 조합에서 group2의 조합을 더했을 때 가방 최대 무게 C를 넘기지 않는 group2의 인덱스를 upper_bound 함수를 통해 이분 탐색으로 찾아내어서 ans변수에 카운트해주었다. 시간복잡도는 O(2^(N/2)log2^(N/2)) = O(N*2^(N/2)) 이다.
반응형
'🧩PS > 🥇Hard' 카테고리의 다른 글
[C/C++] 백준 9252번 - LCS 2 (Longest Common Subsequence, 최장 공통 부분 수열) (0) | 2021.01.19 |
---|---|
[C/C++] 백준 2629번 - 양팔저울 (DP풀이) (0) | 2021.01.15 |
[C/C++] 백준 1753번 - 최단경로 (다익스트라) (0) | 2021.01.06 |
[C/C++] 백준 11444번 - 피보나치 수 6 (점화식, 분할 정복) (5) | 2021.01.06 |
[C/C++] 백준 17298번 - 오큰수 (스택) (7) | 2021.01.06 |