【动态规划】之硬币找零问题(难度:1星)

来源:互联网 发布:易语言整人源码大全 编辑:程序博客网 时间:2024/06/08 16:01

#include <stdio.h>/** * 原题: * 假设有几种硬币,如1块、3块、5块,并且数量无限。 * 请找出能够组成某个数目的找零所使用最少的硬币数。 */#define MIN(x,y) (x<y?x:y)#define INF 50000   //一个很大的值,这里可看作无限大#define N 5         //5种硬币#define K 22         //目标为Kstatic int a[N] = {1,3,5,6,7};     //每种硬币的面值/** * 我的思路如下 * 设子问题为:请求出用N种硬币,能够组成目标数值k(k<=K)的最小硬币数minSum * 找出边界:显然k=0,minSum=0,因为凑够0元需要的硬币数肯定是0 *///最容易想到的是递归int solve_1(int k){    if (k == 0)        return  0;    int minSum = INF;    for (int i = 0; i < N; ++i) {        //如果当前硬币面值不大于目标值,比较并求出最小的硬币数        if (k >= a[i]) {            minSum = MIN(minSum, solve_1(k - a[i]) + 1);        }    }    return minSum;}//solve_1基础上可以加一个记忆数组static int memo[K+1];int solve_2(int k){    if (memo[k] < INF)        return memo[k];    if (k == 0)        return memo[k] = 0;    int minSum = INF;    for (int i = 0; i < N; ++i) {        //如果当前硬币面值不大于目标值,比较并求出最小的硬币数        if (k >= a[i]) {            minSum = MIN(minSum, solve_2(k - a[i]) + 1);        }    }    return memo[k] = minSum;}//改良solve_2成为递推static int minSum[K+1];int solve_3(){    minSum[0] = 0;    for (int i = 1; i <= K; ++i) {        minSum[i] = INF;    }    for (int i = 1; i <= K; ++i) {        for (int j = 0; j < N; ++j) {            //如果当前硬币面值不大于目标值,比较并求出最小的硬币数            if (i >= a[j]){                minSum[i] = MIN(minSum[i], minSum[i-a[j]] + 1);            }        }    }    return minSum[K];}int main() {    printf("solve_1:%d\n", solve_1(K));    for (int i = 0; i < K+1; ++i) {        memo[i] = INF;    }    printf("solve_2:%d\n", solve_2(K));//    for (int i = 0; i < K+1; ++i) {//        printf("%d ", memo[i]);//    }    printf("\nsolve_3:%d\n", solve_3());//    for (int i = 0; i < K+1; ++i) {//        printf("%d ", minSum[i]);//    }    return 0;}

运行结果:

solve_1:4solve_2:4solve_3:4





原创粉丝点击