BOJ 12704 Cheating a Boolean Tree (Large)
문제 내용
개의 노드로 이루어진 논리 회로가 주어집니다. 이 논리 회로는 이진 트리 모양으로, 1부터 까지 각 노드에 번호를 매겼을 때 번 이하의 노드는 논리 게이트이고, 나머지 노드는 입력 노드입니다. 번 논리 게이트는 번과 번 노드를 입력으로 받습니다.
각 게이트는 AND 또는 OR 게이트입니다. 당신은 이 논리 회로에서 몇 개의 게이트를 골라 AND를 OR로, 또는 OR를 AND로 바꿀 수 있습니다.
이때, 최종 출력값이 가 되도록 하기 위해 바꿔야 하는 게이트의 최소 개수를 구하세요. 이미 최종 출력값이 라면 답은 0입니다.
입력
첫 번째 줄에 테스트 케이스의 개수 이 주어집니다. ()
각 테스트 케이스에 대해, 첫 줄에 과 가 주어집니다. (, )
다음 개의 줄에 걸쳐서, 1번부터 번 노드의 정보가 와 의 두 값으로 주어집니다. () 가 1이면 AND, 0이면 OR 게이트이고, 가 1이면 이 게이트를 바꿀 수 있음, 0이면 바꿀 수 없음을 의미합니다.
다음 개의 줄에 걸쳐서, 번 노드부터 번 노드까지의 입력 노드의 값이 주어집니다.
출력
각 테스트 케이스에 대해, Case #{테스트 케이스 번호}: {문제의 정답}의 형식으로 출력합니다. 게이트를 어떻게 바꾸더라도 출력값을 로 만들 수 없다면 문제의 정답 대신 IMPOSSIBLE을 출력합니다.
문제 풀이
스포일러
이 문제는 트리 DP로 풀 수 있습니다.
각 서브트리에 대해, 현재 서브트리를 0이나 1로 만들고자 할 때 바꿔야 하는 게이트의 최소 개수를 계산할 수 있습니다. 아예 만들 수 없는 경우는 inf로 둡니다. 그러면, 양쪽의 자식 서브트리의 DP값을 보고 현재 서브트리의 DP값을 다음과 같이 계산할 수 있습니다.
- 현재 게이트가 AND인 경우: 1로 만드는 비용 = 왼쪽을 1로 만드는 비용 + 오른쪽을 1로 만드는 비용, 0으로 만드는 비용 = min(왼쪽 0 + 오른쪽 0, 왼쪽 0 + 오른쪽 1, 왼쪽 1 + 오른쪽 0)
- OR인 경우도 비슷하게 계산합니다.
- 현재 게이트를 바꿀 수 있다면, 게이트가 반대일 때의 비용을 계산한 뒤 1을 더한 것과 각각 min을 취합니다.