[Python] DP_N으로 표현(3단계)

EunBi Na·2022년 3월 22일
0

문제 설명

아래와 같이 5와 사칙연산만으로 12를 표현할 수 있습니다.

12 = 5 + 5 + (5 / 5) + (5 / 5)
12 = 55 / 5 + 5 / 5
12 = (55 + 5) / 5

5를 사용한 횟수는 각각 6,5,4 입니다. 그리고 이중 가장 작은 경우는 4입니다.
이처럼 숫자 N과 number가 주어질 때, N과 사칙연산만 사용해서 표현 할 수 있는 방법 중 N 사용횟수의 최솟값을 return 하도록 solution 함수를 작성하세요.

제한사항

N은 1 이상 9 이하입니다.
number는 1 이상 32,000 이하입니다.
수식에는 괄호와 사칙연산만 가능하며 나누기 연산에서 나머지는 무시합니다.
최솟값이 8보다 크면 -1을 return 합니다.

입출력 예

N number return
5 12 4
2 11 3

입출력 예 설명

예제 #1
문제에 나온 예와 같습니다.

예제 #2
11 = 22 / 2와 같이 2를 3번만 사용하여 표현할 수 있습니다.

알고리즘 구성

N=2에서는 N=1일때의 원소들을 가지고 사칙연산을 진행한다.

N=3에서는 N=1과 N=2의 원소들을 가지고 사칙연산을 진행한다.

여기서 얻어낼 수 있는 규칙은 다음과 같다.

2 = 1+1
3 = 1+2, 2+1
어떤 N에 대한 원소들을 고르려면, 더해서 N이 되는 두 정수 값의 배열들이 사칙연산의 대상이 된다는 것이다.

다시 위의 N=3을 볼 경우, 3은 1+2, 2+1로 만들 수 있으므로, N=1의 원소들과 N=2의 원소들을 가지고 사칙연산을 진행하면 된다.

def solution(N, number):
    dp = [[]]
    for i in range(1, 9):
        temp = []
        for j in range(1, i):
            for k in dp[j]:
                for l in dp[i - j]:
                    temp.append(k + l)
                    if k - l >= 0:
                        temp.append(k - l)
                    temp.append(k * l)
                    if l != 0 and k != 0:
                        temp.append(k // l)
        temp.append(int(str(N) * i))
        if number in temp:
            return i
        dp.append(list(set(temp)))

    return -1

다른 풀이

1) 결과로 N 사용횟수를 return 해야하므로 N 사용 횟수에 따라 집합을 만들고 만들 수 있는 숫자들을 저장한다.
2) 다음 단계로 넘어가기 전, 집합 속에 number가 있다면 해당 단계를 return 한다.
3) 8 단계까지만 확인하면 되기 때문에, 경우의 수가 엄청 많지는 않다.
예를 들어
N이 두 번 사용된 N = 2 집합은

N = 1
N = 1
의 조합에 의해서 만들 수 있다.

N = 3인 집합은,

N = 1
N = 2
조합에 의해서 만들 수 있다.
N=2, N=1 는 앞의 경우와 중복됨을 알 수 있다. 즉 만들고자 하는 사용 횟수 집합 크기의 절반까지 확인한다.

def solution(N, number):
    S = [0, {N}]
    for i in range(2, 9):
        case_set = {int(str(N)*i)}
        for i_half in range(1, i//2+1):  # S[i_half] S[1]
            for x in S[i_half]:
                for y in S[i-i_half]:
                    case_set.add(x+y)
                    case_set.add(x-y)
                    case_set.add(y-x) # y-x 케이스 추가
                    case_set.add(x*y)
                    if x != 0:
                        case_set.add(y//x)
                    if y != 0:
                        case_set.add(x//y)
        if number in case_set:
            return i
        S.append(case_set)
    return -1


print(solution(2, 11))
def solution(N, number):
    S = [{N}]
    for i in range(2, 9):
        lst = [int(str(N)*i)]
        for X_i in range(0, int(i / 2)):
            for x in S[X_i]:
                for y in S[i - X_i - 2]:
                    lst.append(x + y)
                    lst.append(x - y)
                    lst.append(y - x)
                    lst.append(x * y)
                    if x != 0: lst.append(y // x)
                    if y != 0: lst.append(x // y)
        if number in set(lst):
            return i
        S.append(lst)
    return -1
profile
This is a velog that freely records the process I learn.

0개의 댓글