
접근
https://www.acmicpc.net/problem/2632
피자를 판매할 때 연속하는 피자의 조각들로 판매할 수 있습니다. 따라서 m 조각으로 나뉜 피자 A가 1번 조각부터 m번 조각까지 있다고 했을 때 다음과 같이 경우의 수를 확인할 수 있습니다.
1, 1~2, 1~3, 1~4, ... , 1~(m-1), 1~m,
2, 2~3, 2~4, 2~5, ... , 2~m, 2~1
3, 3~4, 3~5, 3~6, ... , 3~1, 3~2
...
m, m~1, m~2, m~3, ... , m~(m-2), m~(m-1)
총 m*m 경우의 수로 보이지만, 1~m, 2~1, 3~2, ... , m~(m-1) 은 모두 피자 전체를 나타내는 조각을 의미하여 중복이고, 추가적으로 피자를 선택하지 않는 0이 더해집니다.
이 과정에서 구매자가 사고 싶어하는 크기의 조각보다 큰 경우는 계산할 필요 없으므로, 위의 조각들을 탐색, 순환하는 과정에서 구매 희망 숫자보다 큰 경우를 제외해줍니다.
같은 과정을 두 피자 모두에게 진행해주면, A 피자를 선택할 수 있는 경우의 수와, B 피자를 선택할 수 있는 경우의 수를 모두 구할 수 있습니다.
이후, 투포인터 방식을 이용하여 A 피자와 B 피자를 선택하는 방식으로 정답을 구할 수 있습니다.
코드
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.*;
public class Main {
  static int T, res;
  static int m, n;
  static int[] A, B;
  static boolean[] check;
  static ArrayList<Integer> AList = new ArrayList<>();
  static ArrayList<Integer> BList = new ArrayList<>();
  public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    T = Integer.parseInt(br.readLine());
    String[] mn = br.readLine().split(" ");
    m = Integer.parseInt(mn[0]);
    n = Integer.parseInt(mn[1]);
    A = new int[m];
    B = new int[n];
    for (int i = 0; i < m; i++) {
      A[i] = Integer.parseInt(br.readLine());
    }
    for (int i = 0; i < n; i++) {
      B[i] = Integer.parseInt(br.readLine());
    }
    br.close();
    for (int i = 0; i < m; i++) {
      check = new boolean[m];
      check[i] = true;
      getSum(A[i], i, i + 1, check, A, AList);
    }
    for (int i = 0; i < n; i++) {
      check = new boolean[n];
      check[i] = true;
      getSum(B[i], i, i + 1, check, B, BList);
    }
    AList.add(0);
    BList.add(0);
    Collections.sort(AList);
    Collections.sort(BList);
    int leftIdx = 0;
    int rightIdx = BList.size() - 1;
    while (leftIdx < AList.size() && 0 <= rightIdx) {
      int lv = AList.get(leftIdx);
      int rv = BList.get(rightIdx);
      if (lv + rv == T) {
        int lc = 0, rc = 0;
        while (leftIdx < AList.size() && AList.get(leftIdx) == lv) {
          lc++;
          leftIdx++;
        }
        while (0 <= rightIdx && BList.get(rightIdx) == rv) {
          rc++;
          rightIdx--;
        }
        res += lc * rc;
      }
      if (lv + rv > T) rightIdx--;
      if (lv + rv < T) leftIdx++;
    }
    System.out.println(res);
  }
  static void getSum(int sum, int sIdx, int eIdx, boolean[] check, int[] arr, List<Integer> list) {
    if (eIdx == arr.length) eIdx = 0;
    list.add(sum);
    if (check[eIdx] == false && sum <= T && eIdx != sIdx - 1) {
      check[eIdx] = true;
      getSum(sum + arr[eIdx], sIdx, eIdx + 1, check, arr, list);
    }
    return;
  }
}더 생각해 볼 것?
...
코드나 내용 관련 조언, 부족한 점 및 질문 언제든 환영합니다!
반응형
    
    
    
  '코딩 > 백준 (JAVA)' 카테고리의 다른 글
| 백준 2638번: 치즈 (Java) (0) | 2022.08.17 | 
|---|---|
| 백준 4256번: 트리 (Java) (0) | 2022.08.16 | 
| 백준 18428번: 감시 피하기 (Java) (0) | 2022.08.14 | 
| 백준 3109번: 빵집 (Java) (0) | 2022.08.13 | 
| 백준 17182번: 우주 탐사선 (Java) (0) | 2022.08.09 | 




최근댓글