알고리즘/백준[문제풀이]

정렬_1026_보물

Leo.K 2023. 11. 16. 11:03

연초에 계획했던 바와는 다르게 또 다시 귀찮음이 용솟음 치며 열심히 알고리즘을 풀고 정리하겠다 했던 다짐이 한 동안 죽어있다가 연말이 되어서야 다시 살아난다. 

나름 직장인이 된지도 어언 만 2년차를 바라보고 있는 시점에 진짜로 다시금 마음을 잡고 꾸준히 공부를 하고자 한다. 
매일 공부를 할 수 있는 주기적인 시간이 나오는 것은 아니지만, 시간이 되는 날에라도 놀지 않고 한 문제씩이라도 문제를 풀면서 개념을 정리하고자 한다. 

오늘 풀어볼 문제는 백준 1026에 속해 있는 정렬 파트 문제이다. 

https://www.acmicpc.net/problem/1026

 

1026번: 보물

첫째 줄에 N이 주어진다. 둘째 줄에는 A에 있는 N개의 수가 순서대로 주어지고, 셋째 줄에는 B에 있는 수가 순서대로 주어진다. N은 50보다 작거나 같은 자연수이고, A와 B의 각 원소는 100보다 작거

www.acmicpc.net

 

문제 분석

  • 길이가 같은 두 개의 정수 배열 A, B가 주어진다. 
  • B의 원소는 순서를 변경하면 안되며 A의 원소만 문제의 목적에 부합하도록 순서를 정렬할 수 있다. 
  • 가장 큰 상금을 얻는 방법은 두 배열의 원소의 곱의 합이 최소가 되는 값을 찾아야 한다. 
  • 배열의 최대 크기는 50이며, 시간 제한 은 2초 약 2억 번의 연산이 가능하기 때문에 중첩 for문을 사용해도 시간 초과의 우려는 적다. 
  • 또한 원소는 100이하의 음이 아닌 정수이기 때문에 음수가 더해져서 총 합이 작아질 우려 또한 없다. 
  • 쉽게 생각하여 곱의 합의 최소를 구하기 위해서는 최솟값과 최댓값을 곱한 합을 구해야 한다는 것이다. 
  • B의 원소는 순서가 고정이기 때문에 그 순서에 맞게 A의 원소를 정렬하여 각 인덱스에 해당하는 곱의 합을 구한다. 

문제 접근 

  • 이 문제를 물리적인 관점으로 바라보면 A의 최솟값이 B의 최댓값의 인덱스와 동일하게 배치되도록 정렬해야 한다. 
  • 하지만 정렬보다 중요한 것은 곱의 합이 최소만 되면 된다는 것. 논리적인 구조를 보면 B의 원소 또한 정렬해도 된다는 것이다. 
  • 물리적인 구조로 맞추다 보면 구조를 짜맞추는 것도 어려울 뿐더러, 그 구조를 맞춰서 구한 곱의 합이 논리적인 구조로 구성한 배열의 곱의 합과 같은 결과가 나올 것이다. 
  • 즉 A는 오름차순, B는 내림차순으로 정렬한 후에 곱의 합을 구하면 된다. 말이 좀 어려우니 간단히 그림으로 예시를 보자.

 

문제에 나와있는 예시1을 보자. 주어진 배열의 형태는 아래와 같다.

 

위의 배열을 물리적인 구조로 A의 최소 * B의 최대를 계산하기 위해 A만 정렬하면 아래의 결과가 나온다.

S = 1 * 2 + 1 * 7 + 0 * 8 + 1 * 3 + 6 * 1 = 18이 된다. 
하지만 위에서 말했듯이 문제에서 제시한 조건을 그대로 B를 정렬하지 않고 B의 구성에 맞게 A를 사용자 정렬하는 것은 효율성이 좋지 않다. 하여 아래와 같이 같은 결과를 도출할 수 있도록 논리적인 구조로 정렬한다. 

핵심은 A의 최소 * B의 최대를 기준으로 두 배열을 정렬한다.

 

 

A를 오름차순, B를 내림차순으로 하던 A을 내림차순, B를 오름차순으로 하던 결과는 같다. 위에서 말한 핵심을 기준으로 두 배열일 반대의 기준으로 정렬되면 된다는 점이다. 아래의 전체 소스를 첨부하는 것으로 글을 마치겠다. 

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;
public class Main {
    public static void main(String[] args) throws  Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        int N = Integer.parseInt(br.readLine());
        ArrayList<Integer> A = new ArrayList<>();
        ArrayList<Integer> B = new ArrayList<>();

        //list A 초기화
        st = new StringTokenizer(br.readLine(), " ");
        for(int i=0; i<N; i++){
            A.add(Integer.parseInt(st.nextToken()));
        }

        st = new StringTokenizer(br.readLine(), " ");
        //list B 초기화
        for(int i=0; i<N; i++){
            B.add(Integer.parseInt(st.nextToken()));
        }

        //A는 오름차순, B는 내림차순
        Collections.sort(A);
        Collections.sort(B, Collections.reverseOrder());

        int S = 0;
        for(int i=0; i<N; i++){
            S += A.get(i) * B.get(i);
        }

        System.out.println(S);
    }
}

'알고리즘 > 백준[문제풀이]' 카테고리의 다른 글

정렬_1744_수 묶기  (0) 2023.11.23
정렬_1946_신입사원  (2) 2023.11.21
Do it! 코딩테스트-기초편. 3_자료구조2  (0) 2023.03.21
동적계획법_2294_동전2  (0) 2022.11.09
동적계획법_9463_스티커  (0) 2022.11.08