ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 2632 피자판매
    Algorithm/BOJ 2021. 4. 2. 13:14
    728x90

    출처: www.acmicpc.net/problem/2632

    분류: 이분탐색


    접근방식

    이분탐색을 통해 해결해볼 수 있었습니다.

    전체적인 풀이 과정은 다음과 같습니다.

    1. 각 피자에서 가능한 피자 조각을 모두 구한다. (n == 1000 이므로 n^2 이면 충분합니다.)

    2. 한쪽 피자에서 선택했을 경우 또는 하지 않을 경우 다른 쪽 피자의 값이 무엇이 되어야 할지 기대할 수 있기 때문에 이를 이분탐색으로 파악합니다.

     

    가능한 피자 조각을 구할 때 주의해야 할 점은 피자 조각이 원형이라는 점입니다.

    주어진 예제처럼 2 2 1 7 2 에서 피자 조각 경우를 구할 때, 원형으로 생각을 해줘야 합니다.

    2 2 1 7 2  - 여기서 1부터 시작한다면 가능한 조합은 

    [1], [1, 7], [1, 7, 2], [1, 7, 2, 2], [1, 7, 2, 2, 2] 

    이 됩니다! 단 이때 마지막 5가지를 모두 선택하는 경우는 중복되니까 한 번만 포함시켜줘야 합니다.

    저는 n-1 까지만 조합을 만들어주고 마지막에 한 번만 5가지를 모두 더한 조각을 추가해주는 방식으로 해결했습니다.

    원형은 % 연산을 사용해서 해결해줄 수 있습니다.

    for i in 0..<arr.count {
      var temp = 0
      for j in i..<i+arr.count-1 {
        temp += arr[j % arr.count]
        table[temp, default: 0] += 1
      }
    }

    그리고 저는 중복되는 건 딕셔너리로 개수만 체크해서 처리해줬습니다 :)

    이때는 a와 b 에서 원하는 조각 조합을 찾았으면

    a 에서 피자 조각 개수 * b에서 피자 조각 개수

    로 처리를 해줘야겠죠?

     

    해결방법

    일단 a 조합에서 n까지를 돌면서 원하는 피자조각 - an 이 b에서 있나 쭉 확인을 했는데

    b 에서만 원하는 피자 조각이 또 있는지 확인해줘야 해서 포문을 나오고 한 번 더 처리를 해줬습니다,.

    더 효율적으로 처리할 수도 있을 거 같네요 @_@

     

    let n = Int(readLine()!)!
    let nm = readLine()!.split(separator: " ").map { Int(String($0))! }
    var a = [Int]()
    var b = [Int]()
    for _ in 0..<nm[0] {
      a.append(Int(readLine()!)!)
    }
    
    for _ in 0..<nm[1] {
      b.append(Int(readLine()!)!)
    }
    
    func sum(_ arr: [Int]) -> [Int: Int] {
      var table = [Int: Int]()
      for i in 0..<arr.count {
        var temp = 0
        for j in i..<i+arr.count-1 {
          temp += arr[j % arr.count]
          table[temp, default: 0] += 1
        }
      }
      table[arr.reduce(0, +), default: 0] += 1
      return table
    }
    
    let aTable = sum(a)
    let bTable = sum(b)
    
    let sumA = [Int](aTable.keys).sorted()
    let sumB = [Int](bTable.keys).sorted()
    
    var resultCase = 0
    
    for an in sumA where an <= n  {
      guard an != n else {
        resultCase += aTable[an]!
        break
      }
      
      if let bn = binarySearch(n-an) {
        resultCase += aTable[an]! * bTable[bn]!
      }
    }
    
    if let bn = binarySearch(n), let bCase = bTable[bn] {
      resultCase += bCase
    }
    
    func binarySearch(_ target: Int) -> Int? {
      var low = 0
      var high = sumB.count-1
      
      while low <= high {
        let mid = (low + high) / 2
        
        if sumB[mid] == target {
          return sumB[mid]
        } else if target < sumB[mid] {
          high = mid-1
        } else {
          low = mid+1
        }
      }
      
      return nil
    }
    
    print(resultCase)

     

    배운점

    피자조각 개수를 미리 구해놓는 데서 머리가 좀 안 굴러갔는데

    찬찬히 적어가면서 이해를 했다.

    메모메모..!

    'Algorithm > BOJ' 카테고리의 다른 글

    백준 17825 주사위 윷놀이  (0) 2021.04.04
    백준 17779 게리맨더링 2  (0) 2021.04.04
    백준 1981 배열에서 이동  (0) 2021.04.01
    백준 3020 개똥벌레  (0) 2021.03.31
    백준 1520 내리막 길  (0) 2021.03.30

    댓글

Designed by Tistory.