PS/백준
[백준] 2632 피자 판매
HUN
2021. 4. 11. 18:08

피자는 A 종류 이거나 B 종류이거나 A와 B 혼합하여 판매할 수 있다. 그리고 한 종류의 피자 조각 을 2개 이상 판매할 때 그 조각들은 반드시 연속해야한다.
'조각들이 연속해야한다'는 부분에서 A와 B 각각 누적합을 구해야함을 알 수 있다. 그리고 구해진 누적합을 이분탐색을 통해 고객이 원하는 피자의 크기를 구할 수 있다.
누적합 구하기
피자는 원형이기 때문에 순환 배열(Circular Array) 누적합을 구해야한다. start(front), end(rear) 포인터를 사용해야한다.
start와 end 포인터를 한 칸씩 이동하면서 누적합을 구한다. 단 start 포인터가 다시 0이 되면 종료한다.
start에서 end까지 모든 수의 누적합이 구매자가 원하는 크기 보다 작거나 같을 경우 조각의 개수 만큼 중복된다.
따라서 start ~ end-1까지 누적합을 구하고 마지막에 start ~ end까지 누적합이 구매자가 원하는 크기 보다 작을 경우 누적합 배열에 포함 시킨다.
이분 탐색
left, right 투 포인터를 사용한다. left는 A 피자의 첫 번째 누적합 원소를 가리키는 포인터이다. right는 B 피자의 마지막 누적합 원소를 가리키는 포인터이다.
Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from sys import stdin | |
from collections import defaultdict | |
readline = stdin.readline | |
T = int(readline()) | |
N, M = map(int, readline().split()) | |
A = [int(readline()) for _ in range(N)] | |
B = [int(readline()) for _ in range(M)] | |
def solve(): | |
stack_sum_A = list(sorted(get_stack_sum(A))) | |
stack_sum_B = list(sorted(get_stack_sum(B))) | |
A_count = get_count_as_dict(stack_sum_A) | |
B_count = get_count_as_dict(stack_sum_B) | |
res = binary_search(A_count, B_count) | |
print(res) | |
def get_count_as_dict(arr): | |
count = defaultdict(int) | |
for a in arr: | |
if a not in count.keys(): | |
count[a] = 0 | |
count[a] += 1 | |
return count | |
def binary_search(dict1, dict2): | |
arr1 = list(sorted(list(dict1.keys()))) | |
arr2 = list(sorted(list(dict2.keys()))) | |
left, right = 0, len(arr2) - 1 | |
res = dict1[T] + dict2[T] | |
while left < len(arr1) and right >= 0: | |
cur = arr1[left] + arr2[right] | |
if cur > T: | |
right -= 1 | |
elif cur < T: | |
left += 1 | |
else: | |
res += (dict1[arr1[left]] * dict2[arr2[right]]) | |
left += 1 | |
right -= 1 | |
return res | |
# 누적합 | |
# Circular | |
def get_stack_sum(arr): | |
res = [] | |
start = 0 | |
end = len(arr) - 1 | |
# 순환 배열 누적합 | |
while True: | |
_sum = 0 | |
i = start | |
while i != end: | |
_sum += arr[i] | |
if _sum > T: break | |
res.append(_sum) | |
i = (i + len(arr) + 1) % len(arr) | |
start = (start + len(arr) + 1) % len(arr) | |
end = (start + len(arr) - 1) % len(arr) | |
# 시작점이 다시 처음으로 돌아오면 종료 | |
if start == 0: break | |
_sum = sum(arr) | |
if _sum <= T: | |
res.append(_sum) | |
return res | |
solve() |
Java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.*; | |
import java.io.*; | |
public class BOJ2632 { | |
static int T, N, M; | |
public static void main(String[] args) throws IOException{ | |
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | |
T = Integer.parseInt(br.readLine()); | |
StringTokenizer st = new StringTokenizer(br.readLine()); | |
N = Integer.parseInt(st.nextToken()); | |
M = Integer.parseInt(st.nextToken()); | |
int[] A = new int[N]; | |
int[] B = new int[M]; | |
for(int i=0;i<N;i++){ | |
A[i] = Integer.parseInt(br.readLine()); | |
} | |
for(int i=0;i<M;i++){ | |
B[i] = Integer.parseInt(br.readLine()); | |
} | |
int[] stackSumA = getStackSum(A); | |
int[] stackSumB = getStackSum(B); | |
Map<Integer, Integer> ACount = getCountAsMap(stackSumA); | |
Map<Integer, Integer> BCount = getCountAsMap(stackSumB); | |
binarySearch(ACount, BCount); | |
} | |
public static int[] getStackSum(int[] arr){ | |
ArrayList<Integer> res = new ArrayList<>(); | |
int start = 0; | |
int end = arr.length - 1; | |
while(true){ | |
int i = start; | |
int sum = 0; | |
while(i != end){ | |
sum += arr[i]; | |
if(sum > T) break; | |
res.add(sum); | |
i = (i + arr.length + 1) % arr.length; | |
} | |
start = (start + arr.length + 1) % arr.length; | |
end = (start + arr.length - 1) % arr.length; | |
if(start == 0) break; | |
} | |
int sum = 0; | |
for(int i=0;i<arr.length;i++){ | |
sum += arr[i]; | |
} | |
if(sum <= T){ | |
res.add(sum); | |
} | |
int[] returnValue = new int[res.size()]; | |
for(int i=0;i<res.size();i++){ | |
returnValue[i] = res.get(i); | |
} | |
return returnValue; | |
} | |
public static void binarySearch(Map<Integer, Integer> ACount, Map<Integer, Integer> BCount){ | |
ArrayList<Integer> arr1 = new ArrayList<>(ACount.keySet()); | |
ArrayList<Integer> arr2 = new ArrayList<>(BCount.keySet()); | |
Collections.sort(arr1); | |
Collections.sort(arr2); | |
int left = 0, right = arr2.size() - 1; | |
int res = ACount.getOrDefault(T, 0) + BCount.getOrDefault(T, 0); | |
while(left < arr1.size() && right >= 0){ | |
int cur = arr1.get(left) + arr2.get(right); | |
if(cur > T){ | |
right--; | |
} else if(cur < T){ | |
left++; | |
} else { | |
res += (ACount.get(arr1.get(left)) * BCount.get(arr2.get(right))); | |
left++; | |
right--; | |
} | |
} | |
System.out.println(res); | |
} | |
public static Map<Integer, Integer> getCountAsMap(int[] arr){ | |
Map<Integer, Integer> count = new HashMap<>(); | |
for(int num : arr){ | |
count.put(num, count.getOrDefault(num, 0) + 1); | |
} | |
return count; | |
} | |
} |
728x90