전공책16508

LJM·2023년 1월 17일
0

백준풀기

목록 보기
38/259

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

처음에 풀이를 안보고 어떻게 풀지 고민했을때는 방향이 전혀 잡히지 않았다

ANT 를 만들려고 한다면 ANT 글자를 어떻게 만들수 있을지에만 골똘히 집중했었다

답이 안나와서 다른 사람들의 풀이를 보고 책을 중심으로 풀어야 한다는것을 알게 되었다

그래서 책을 조합하는 것부터 만들어야 한다는 생각을 하였다. 0번책 1번책 2번책 3번책이 있다면 다음과 같은 탐색을 해야겠다고 생각하였다

책을 하나만 선택하는 경우
책을 두권 선택하는 경우
책을 세권 선택하는 경우
책을 네권 선택하는 경우...
모든 가능한 조합을 생성하도록 재귀함수를 작성하는 것부터 하였다. 마치 이진분할 트리를 DFS로 탐색하는 것과 같다

그리고 조합된 책으로 ANT 란 글자를 만들 수있는지 확인하고 만들수 있다면 책의 가격을 minPrice 로 저장하는 방식으로 풀었다

import java.io.*;
import java.util.Arrays;

class Book
{
    String name;
    int price;

    int[] alphabetCnt;
    public Book(int price, String name) {
        this.name = name;
        this.price = price;

        alphabetCnt = new int[26];

        for(int i = 0; i < name.length(); ++i)
        {
            alphabetCnt[name.charAt(i) - 'A']++;
        }
    }
}

public class Main {

    static Book[] books;
    static int[] bookSelect;

    static boolean[] checked;

    static int N;

    static String T;

    static int[] needAlphabetCnt = new int[26];

    static int minPrice = Integer.MAX_VALUE;

    public static void main(String[] args) throws IOException
    {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        T = br.readLine();

        for(int i = 0; i < T.length(); ++i)
        {
            needAlphabetCnt[T.charAt(i) - 'A']++;
        }

        N = Integer.parseInt(br.readLine());
        books = new Book[N];
        bookSelect = new int[N];
        checked = new boolean[N];

        String[] input;
        for(int i = 0; i < N; ++i)
        {
            input = br.readLine().split(" ");
            books[i] = new Book(Integer.parseInt(input[0]), input[1]);
        }

        //책의 조합을 만드는 함수. 완전탐색. DFS
        search(0, 1);

        if(Integer.MAX_VALUE == minPrice)//실패!
        {
            System.out.println(-1);
        }
        else
            System.out.println(minPrice);
    }

    static void search(int depth, int targetDepth)
    {
        if(depth == targetDepth)
        {

//            for(int i = 0; i < depth; ++i)
//            {
//                System.out.print(bookSelect[i]);
//            }
//            System.out.println();

            canMakeSentence(depth);

            return;
        }

        for(int i = bookSelect[depth==0?depth:depth-1]; i < N; ++i)
        {
            if(checked[i])
                continue;

            checked[i] = true;
            bookSelect[depth] = i;
            search(depth+1, targetDepth);
            search(depth+1, targetDepth+1);
            checked[i] = false;
        }
    }

    static void canMakeSentence(int curDepth)
    {
        int[] alphabetCnt = new int[26];

        int price = 0;

        for(int i = 0; i < curDepth; ++i)
        {
            price += books[bookSelect[i]].price;
            for(int j =0; j < 26; ++j)
            {
                alphabetCnt[j] += books[bookSelect[i]].alphabetCnt[j];
            }

        }

        for(int i = 0; i < 26; ++i)
        {
            if(needAlphabetCnt[i] > alphabetCnt[i])
            {
                return;
            }
        }

        minPrice = Math.min(minPrice, price);

    }
}
profile
게임개발자 백엔드개발자

0개의 댓글