문제

boj1493

greedy + dnc로 푸는 문제. 큐브를 최소한 사용하기 때문에 갖고 있는 큐브 중 가장 큰 큐브부터 집어넣는다. 그 다음에는 큐브를 채운 나머지 부분을 세 개의 직육면체로 나눠 동일한 작업을 반복하면 된다!

구현

#include <iostream>
#include <vector>
#include <utility> // pair
#include <algorithm>
#include <cmath> // pow
using namespace std;

int L, W, H, cnt;
bool flag = true;
vector< pair<int, int> > cubes; // (pow, cnt)

bool cmp(pair<int, int> a, pair<int, int> b) {
	return a.first > b.first;
}

void solve(int l, int w, int h, int now) {
	if (l == 0 || w == 0 || h == 0) return;

	int i;
	int m = min(l, min(w, h));

	for (i = now; i < cubes.size(); i++) {
		if (cubes[i].second && m >= cubes[i].first) {
			int tmp = cubes[i].first; //현재 가장 큰 큐브의 변의 길이
			cubes[i].second--; // 사용할거니까 재고를 줄임
			cnt++; // 사용한 큐브의 개수 증가
			// 전체에서 사용한 큐브를 제외한 나머지 부분을 세 개로 나눠 동일한 작업 반복
			solve(l - tmp, w, h, i);
			solve(tmp, w - tmp, h, i);
			solve(tmp, tmp, h - tmp, i);
			return;
		}
	}
	flag = false;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	int N, ans, i, tmp1, tmp2;
	cin >> L >> W >> H;
	cin >> N;

	for (i = 0; i < N; i++) {
		cin >> tmp1 >> tmp2;
		cubes.push_back(make_pair(int(pow(2, tmp1)), tmp2));
	}

	sort(cubes.begin(), cubes.end(), cmp);
	solve(L, W, H, 0);

	if (flag) cout << cnt << endl;
	else cout << "-1" << endl;
	return 0;
}