Koder / 박성훈
article thumbnail

kks227님 그리디 정주행 완료

마지막문제라 그런지 까다로웠음.

 

그리디에 있기보단 얜 분할정복으로 빼야할거같은데 ㅁㄴㅇㄹ

https://www.acmicpc.net/problem/1493

 

1493번: 박스 채우기

세준이는 length × width × height 크기의 박스를 가지고 있다. 그리고 세준이는 이 박스를 큐브를 이용해서 채우려고 한다. 큐브는 정육면체 모양이며, 한 변의 길이는 2의 제곱꼴이다. (1×1×1, 2×2×2,

www.acmicpc.net

암튼 이 문제는 매우 친절하게도 모든 상자가 2^k 꼴이라

큰 상자는 더 작은 상자 8개로 분해될수 있다.

 

그래서 무조건 큰 상자를 많이 넣는게 이득이므로,

최대한 큰 박스를 하나 우겨넣고 남은 입체도형을

7등분해서

k*k*k 정육면체를 포함한 여덟개의 도형으로 나눠 분할정복하면

문제를 해결할 수 있다.

 

풀고나서 풀이 까봤는데 보통 세개로 많이 나누던데

개인적으로 7개가 더 직관적인듯?

근데 7개로 쪼개면 시간복잡도가 타이트해지는지

pow(2,i) 로 k를 계산하면 tle를 받는다.

1<<i 로 바꿔주자.

 

더보기
#include <bits/stdc++.h>
using namespace std;

int num[123] = {0};
bool flag = 1;
long long int ans = 0;

int fill(int x, int y, int z){
	if(!(x&&y&&z)) return 0;
	
	for(int i=19; i>=0; i--){
		int k = 1<<i;
		if(num[i] && x>=k && y>=k && z>=k){
			num[i]--;
			ans++;
			fill(x-k,k,k);
			fill(k,y-k,k);
			fill(k,k,z-k);
			fill(x-k,y-k,k);
			fill(k,y-k,z-k);
			fill(x-k,k,z-k);
			fill(x-k,y-k,z-k);
			return 0;
		}
	}
	flag = false;
	return 0;
}

int main(){
	int x,y,z,n,a,b;
	cin >> x >> y >> z;
	cin >> n;
	
	for(int i=0; i<n; i++){
		cin >> a >> b;
		num[a] = b;
	}
	
	fill(x,y,z);
	
	if(!flag) cout << -1;
	else      cout << ans;
	
	return 0;
}

반응형