본문 바로가기
알고리즘/백준

백준 1450 냅색문제 C++

by ash9river 2024. 11. 25.

 

간단한 해설

 

이전 포스팅과 비슷하게 2^30의 경우의 수이므로 meet in middle러 2^15, 2^15로 나눈다.

 

기존 논지는 이전 포스팅과 비슷하다.

 

백준 1208 부분수열의 합 2 C++

간단한 해설 meet in middle을 활용하면 된다. 중간에서 만나기를 활용하지 않을 경우, n이 최대 40이라서 부분 수열의 개수가 2^40의 경우가 나오게 된다. 그러나, 중간에서 만나기를 활용하는 경우

ash9river.tistory.com

 

ll rightIdx=upper_bound(rightPartialSum.begin(),rightPartialSum.end(),limitVal)-rightPartialSum.begin();
ans+=rightIdx;

 

c- 왼쪽 부분수열의 값을 target으로한 upper_bound의 인덱스를 더하는게 포인트

개수이므로 자동으로 +1이 된 값이고 만약, 값이 존재하지 않으면 0이 더해지기 때문이다.

 

공집합도 경우의 수로 치기 때문에 결과값에 +1을 해주어야한다.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define ll long long
vector<ll> v;
vector<ll> leftV;
vector<ll> rightV;
vector<ll> leftPartialSum;
vector<ll> rightPartialSum;
vector<ll> picker;
ll n,c,mid;
void leftPick(int toPick){
	if(toPick==0){
		ll tmpSum=0;
		for(ll k:picker) tmpSum+=leftV[k];
		leftPartialSum.push_back(tmpSum);
		return;
	}
	int idx=picker.empty()?0:picker.back()+1;
	for(int i=idx;i<leftV.size();++i){
		picker.push_back(i);
		leftPick(toPick-1);
		picker.pop_back();
	}
}
void rightPick(int toPick){
	if(toPick==0){
		ll tmpSum=0;
		for(ll k:picker) tmpSum+=rightV[k];
		rightPartialSum.push_back(tmpSum);
		return;
	}
	int idx=picker.empty()?0:picker.back()+1;
	for(int i=idx;i<rightV.size();++i){
		picker.push_back(i);
		rightPick(toPick-1);
		picker.pop_back();
	}
}
int main(){
	cin.tie(0);
	ios_base::sync_with_stdio(0);
	cin>>n>>c;
	v.resize(n);
	for(int i=0;i<n;++i){
		cin>>v[i];
	}
	mid=n/2;
	sort(v.begin(),v.end());
	for(int i=0;i<mid;++i){
		leftV.push_back(v[i]);
	}
	for(int i=mid;i<n;++i){
		rightV.push_back(v[i]);
	}
	for(int i=leftV.size();i>0;--i){
		leftPick(i);
	}
	for(int i=rightV.size();i>0;--i){
		rightPick(i);
	}
	sort(rightPartialSum.begin(),rightPartialSum.end());
	ll ans=0;
	for(int i=0;i<leftPartialSum.size();++i){
		ll val=leftPartialSum[i];
		if(val>c) continue;
		++ans;
		ll limitVal=c-val;
		ll rightIdx=upper_bound(rightPartialSum.begin(),rightPartialSum.end(),limitVal)-rightPartialSum.begin();
		ans+=rightIdx;
	}
	for(auto it=rightPartialSum.begin();it!=rightPartialSum.end();++it){
		ll val=*it;
		if(val>c) break;
		++ans;
	}
	cout<<ans+1;
}

'알고리즘 > 백준' 카테고리의 다른 글

백준 5052 전화번호 목록 C++  (0) 2024.12.11
백준 7490 0 만들기 C++  (0) 2024.11.29
백준 1208 부분수열의 합 2 C++  (0) 2024.11.25
백준 7453 합이 0인 네 정수 C++  (0) 2024.11.18
백준 13164 행복 유치원 C++  (0) 2024.11.18