WonYong-Jang / algorithm

0 stars 0 forks source link

동전 교환 / 냅색 알고리즘 #1

Open WonYong-Jang opened 6 years ago

WonYong-Jang commented 6 years ago

관련 문제

백준 11047 동전0 https://www.acmicpc.net/problem/11047 2293 동전1 https://www.acmicpc.net/problem/2293 2294 동전2 https://www.acmicpc.net/problem/2294 7579 앱 https://www.acmicpc.net/problem/7579 1660 캡틴 이다솜 https://www.acmicpc.net/problem/1660 4781 사탕 가게 https://www.acmicpc.net/problem/4781 9084 동전 https://www.acmicpc.net/problem/9084 2624 동전 바꿔주기 https://www.acmicpc.net/problem/2624 2629 양팔저울 https://www.acmicpc.net/problem/2629 1398 동전 문제 https://www.acmicpc.net/problem/1398

WonYong-Jang commented 5 years ago

관련 문제

동전 0 - https://www.acmicpc.net/problem/11047

준규가 가지고 있는 동전은 총 N종류이고, 각각의 동전을 매우 많이 가지고 있다.
동전을 적절히 사용해서 그 가치의 합을 K로 만들려고 한다. 이때 필요한 동전 개수의 최솟값을 구하는 프로그램을 작성하시오.

동전 1 - https://www.acmicpc.net/problem/2293

2019-01-09 5 00 36
public class baek2293 {

    static int N, K;
    static int[] coin = new int[101]; // 보유한 동전 종류 
    static int[][] dp = new int[101][10001]; 
    // N(n, k) : 거스름돈 K 원을 n개의 동전으로 만들수 있는 조합의 수 
    public static void main(String[] args) throws IOException {

        for(int i=1; i<= N; i++)
        {
            st = new StringTokenizer(br.readLine());
            coin[i] = Integer.parseInt(st.nextToken());
            dp[i][0] = 1;
            // 거스름돈 k를 k-coin[i] 했을때 0이 나온 경우는 딱 맞게 거슬러줄수 있는 경우의 수 
        }

        int num = 0;
        // 가진 동전들의 조합의 수
        //ex) 1을 만들수 있는 가짓수를 구해놓고 2를 만들수 있는 수 구할때 1을 만든 가짓수를 더해가면서 구함 
        for(int i=1; i<= N; i++)  
        {
            for(int j=1; j<= K; j++) // 구할 거스름돈 가격 
            {
                if(j - coin[i] < 0) num = 0; // base case 
                else num = dp[i][j-coin[i]]; // 동전 coin[i] 으로 만들수 있는 경우 

                dp[i][j] = dp[i-1][j] + num; // 이전에 만들어 놓은 갯수와 축적 
            }
        }

        System.out.println(dp[N][K]);
    }
}

메모리 절약 방법 !

dp[0] = 1;
int num = 0;
// 가진 동전들의 조합의 수
//ex) 1을 만들수 있는 가짓수를 구해놓고 2를 만들수 있는 수 구할때 1을 만든 가짓수를 더해가면서 구함 
for(int i=1; i<= N; i++)  
{
    for(int j=1; j<= K; j++) // 구할 거스름돈 가격 
    {
        if(j - coin[i] < 0) num = 0; // base case 
        else num = dp[j-coin[i]]; // 동전 coin[i] 으로 만들수 있는 경우 

        dp[j] += num; // 이전에 만들어 놓은 갯수와 축적 
    }
}

동전 2 - https://www.acmicpc.net/problem/2294

2019-01-08 9 23 08
public class Main {

    static final int INF = 987654321;
    static int N, K;
    static int[] coin = new int[105];
    static int[] coinCnt = new int[10005]; // 최소 동전 갯수 저장 배열 
    static int[] lastCoin = new int[10005]; // 마지막 사용 동전 기록 ( 어느 동전 썻는지 확인 가능 )
    public static void main(String[] args) throws IOException {
        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());

        for(int i=1; i<= N; i++)
        {
            st = new StringTokenizer(br.readLine());
            coin[i] = Integer.parseInt(st.nextToken());
        }
        for(int i=1; i<= K; i++)
        {
            coinCnt[i] = INF;
            for(int j=1; j<= N; j++)
            {
                if(i - coin[j] >= 0)
                {
                    if(coinCnt[i] > coinCnt[i-coin[j]] + 1)
                    {
                        coinCnt[i] = coinCnt[i-coin[j]] + 1;
                        lastCoin[i] = coin[j];
                    }
                }
            }
        }
        if(coinCnt[K] == INF) System.out.println(-1);
        else System.out.println(coinCnt[K]);
    }
    public static int min(int a, int b) { return a > b ? b : a; }
}
WonYong-Jang commented 5 years ago

백준 1398 ( 동전 0 예외 문제 )

풀이

위의 각 단계가 100 으로 나눌때와 똑같기 때문에 dp를 1부터 99까지만 구해 놓고 구해도 답이 같음 한단계가 100으로 나눌 때 같아지는 것을 이용한 풀이입니다. dp를 이용해서 0~99까지 최소 코인 수를 구합니다.

public class Main {

    public static int len;
    public static long N;
    public static int INF;
    public static int[] dp = new int[100];
    public static int[] coin = {1, 10, 25};
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int testCase = Integer.parseInt(st.nextToken());
        INF = Integer.MAX_VALUE;

                // 1 번 부터 99까지 최소 동전 갯수 구해놓기 / 동전1 구하는 dp 방법 이용
        for(int i=1; i< 100; i++) 
        {
            dp[i] = INF;
            for(int j=0; j<3; j++)
            {
                if(i - coin[j] >= 0)
                {
                    dp[i] = min(dp[i], dp[i-coin[j]] + 1);
                }
            }
        }

        for(int k=1; k<= testCase; k++)
        {
            st = new StringTokenizer(br.readLine());
            N = Long.parseLong(st.nextToken());
            long cnt = 0;
            while(N > 0)
            {
                int result = (int) (N % 100);
                cnt += dp[result];
                N /= 100;
            }
            System.out.println(cnt);
        }
    }
}