Thief of Wealth
Published 2020. 10. 9. 01:41
1493 박스 채우기 개발/알고리즘

문제

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

세준이가 가지고 있는 박스의 종류와 큐브의 종류와 개수가 주어졌을 때, 박스를 채우는데 필요한 큐브의 최소 개수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 세 자연수 length width height가 주어진다.

둘째 줄에 세준이가 가지고 있는 큐브의 종류의 개수 N이 주어진다.

셋째 줄부터 총 N개의 줄에 큐브의 종류 Ai와 개수 Bi가 순서대로 주어진다. 큐브의 종류는 한 변의 길이를 나타낼 때 쓰는 2i에서 i이다.

출력

첫째 줄에 필요한 큐브의 개수의 최솟값을 출력한다. 만약 채울 수 없다면 -1을 출력한다.

 

 

이건 내가 아는 한 역대급으로 어려운 문제였다.

 

1. 동전문제 처럼 풀어서 틀렸다.

2. 남은 공간의 정보를 구하는 힌트를 얻어서 구현해서 시간초과 + 메모리 초과

3. 재귀적인 방법을 찾아서 구현했더니 시간초과

4. 수학적으로 아주 어렵게 푼 공식. (이건 절대 못떠올린다.)

 

C++로 3번이 통과하는것 같은데 2번은 c++로 해도 메모리초과가 났었을 것같다.

 

숫자의 범위가 좀 작았어도 2번으로 풀 수 있었는데, 방법을 강구하다가 너무 많은 시간을 소모해버렸다 ㅠㅠ

 

1. 동전던지기 처럼 풀었다가 틀림

 

import sys
input = sys.stdin.readline

length, width, height = map(int, input().rstrip().split(" "))
n = int(input().rstrip())

cubes = []
for _ in range(n):
    a, b = map(int, input().rstrip().split(" "))
    cubes.append((a, b))
    # for i in range(b):
    #     cubes.append((2**a)**3)

volume = length*width*height

count = 0
while(volume > 0 and len(cubes) > 0):
    line, num = cubes.pop()
    v = (2**line)**3
    for i in range(num):
        if(volume > 0):
            volume -= v
            count += 1


print(count)

 

2. 공간계산해서 풀었더니 메모리+시간초과

import sys
import heapq
input = sys.stdin.readline

length, width, height = map(int, input().rstrip().split(" "))
n = int(input().rstrip())

cubes = []
for _ in range(n):
    a, b = map(int, input().rstrip().split(" "))
    cubes.append([2**a, b])

totalVolume = length*width*height


def getLargestCube():  # 가장 큰 크기의 큐브를 반환한다.
    global cubes

    if(len(cubes) == 0):  # 큐브가 없으면 -1 반환
        return -1

    # 가장 큰 큐브의 개수가 0이상이면 개수를 1개 줄이고 반환한다.
    if(cubes[-1][1] > 0):
        cubes[-1][1] -= 1
        return cubes[-1][0]  # 큐브 크기 반환
    # 개수가 0개이면
    else:
        cubes.pop()  # 0개인거 제거
        return getLargestCube()


def marginSpace(l, w, h, line):  # 공간과 큐브의 한 변이 주어졌을때 나머지 공간 반환
    res = []
    if(h-line > 0):
        res.append((l, w, h-line))
    if(w-line > 0):
        res.append((line, w-line, line))
    if(l-line > 0):
        res.append((l-line, w, line))
    return res


def solve(length, width, height):
    global cubes, totalVolume
    # 크기순 정렬
    cubes = sorted(cubes, key=lambda x: x[0])

    count = 0

    q = []
    heapq.heappush(q, (-1*length*width*height, length, width, height))

    cube_line = 0  # 초기화
    while(len(q) != 0):
        # print(q)
        _, l, w, h = heapq.heappop(q)  # 부피가 큰것부터 꺼낸다.
        # 큐브 준비
        cube_line = getLargestCube()

        if(cube_line == -1):
            break
        # 유효한 범위에 모든 조건이 부합하면
        if(l >= cube_line and w >= cube_line and h >= cube_line):
            count += 1  # 큐브를 넣는다!
            totalVolume -= cube_line**3  # 총 볼륨을 빼준다.
            # 큐브를 넣은 후의 공간을 구한다.
            spaces = marginSpace(l, w, h, cube_line)
            # 구한 공간을 큐에 넣는다

            for i in range(len(spaces)):
                x, y, z = spaces[i]
                if(x > 0 and y > 0 and z > 0):
                    heapq.heappush(q, [-1*x*y*z, x, y, z])
        else:
            cubes.pop()
            heapq.heappush(q, [_, l, w, h])

    return count


ans = solve(length, width, height)

# 빈공간이 남아있다면 -1
if(totalVolume > 0):
    print(-1)
else:
    print(ans)

# print(totalVolume)
# print(ans)

3. 재귀방식으로 풀었더니 시간초과

import sys
sys.setrecursionlimit(10**6)
input = sys.stdin.readline

length, width, height = map(int, input().rstrip().split(" "))
n = int(input().rstrip())

cubes = []
for _ in range(n):
    a, b = map(int, input().rstrip().split(" "))
    cubes.append([2**a, b])
cubes = sorted(cubes, key=lambda x: -x[0])
count = 0

PF = True


def recursive_func(l, w, h):
    global PF, cubes, count
    if(PF == False):
        return
    if(l == 0 or w == 0 or h == 0):
        return
    for i in range(len(cubes)):
        if(cubes[i][1] > 0 and l >= cubes[i][0] and w >= cubes[i][0] and h >= cubes[i][0]):
            count += 1
            cubes[i][1] -= 1

            recursive_func(l, w, h-cubes[i][0])
            recursive_func(cubes[i][0], w-cubes[i][0], cubes[i][0])
            recursive_func(l-cubes[i][0], w, cubes[i][0])

            return
    PF = False
    return


recursive_func(length, width, height)

if(PF == False):
    print(-1)
else:
    print(count)

4. 수학공식

 

import sys
sys.setrecursionlimit(10**6)
input = sys.stdin.readline

length, width, height = map(int, input().rstrip().split(" "))
n = int(input().rstrip())

cubes = [0] * 21
for _ in range(n):
    a, b = map(int, input().rstrip().split(" "))
    cubes[a] += b

total = 0
count = 0
for i in range(19, -1, -1):
    total <<= 3
    t = min(cubes[i], (length >> i)*(width >> i)*(height >> i) - total)
    total += t
    count += t

if(total == length*width*height):
    print(count)
else:
    print(-1)

 

 

솔직히 다시는 만나고 싶지 않은 문제이다.

'개발 > 알고리즘' 카테고리의 다른 글

[BOJ] 1766 문제집  (0) 2020.10.09
[BOJ] 2529 부등호  (0) 2020.10.09
위상 정렬이란?  (0) 2020.10.08
2512 예산  (0) 2020.10.07
2212 센서  (0) 2020.10.07
profile on loading

Loading...