九度OJ 1209: 最小邮票数

来源:互联网 发布:淘宝新店提取软件 编辑:程序博客网 时间:2024/05/17 03:26
题目描述:

    有若干张邮票,要求从中选取最少的邮票张数凑成一个给定的总值。
    如,有1分,3分,3分,3分,4分五张邮票,要求凑成10分,则使用3张邮票:3分、3分、4分即可。

输入:

    有多组数据,对于每组数据,首先是要求凑成的邮票总值M,M<100。然后是一个数N,N〈20,表示有N张邮票。接下来是N个正整数,分别表示这N张邮票的面值,且以升序排列。

输出:

      对于每组数据,能够凑成总值M的最少邮票张数。若无解,输出0。

样例输入:
1051 3 3 3 4
样例输出:
3
来源:

2007年清华大学计算机研究生机试真题


题目分析:


这是一个0-1背包问题,可采用动态规划来解答。这应该是07年3个题中难度最大的一个。

源代码1(略显笨拙,将dp过程存在二维数组中)


#include <stdio.h>#include <stdlib.h> int main(){    int m, n;    while(scanf("%d%d", &m, &n) != EOF)    {        int value[20] = {0};        int i, j;        for(i=1; i<=n; i++)            scanf("%d", &value[i]);        int num[30][150] = {0};        for(i = 0; i <= n; i++)            for(j = 0; j <= m; j++)            {                if(j == 0)                    num[i][j] = 0;                else if(i == 0)                    num[i][j] = -1;                else                {                    if(j < value[i])                        num[i][j] = num[i-1][j];                    else                    {                        int a = num[i-1][j];                        int b = num[i-1][j-value[i]];                        if(a == -1 && b == -1)                            num[i][j] = -1;                        else if(a >= 0 && b == -1)                            num[i][j] = a;                        else if(a == -1 && b >= 0)                            num[i][j] = b + 1;                        else                            num[i][j] = a<(b+1) ? a:(b+1);                    }                }            }        if(num[n][m] == -1)            num[n][m] = 0;        printf("%d\n", num[n][m]);    }    //system("pause");    return 0;}/**************************************************************    Problem: 1209    User: superlc320    Language: C++    Result: Accepted    Time:70 ms    Memory:1020 kb****************************************************************/

源代码2(参考某大神的,dp过程存在一维数组中)


#include <stdio.h>#include <stdlib.h>#define INF 1000000000 int min(int a, int b)  {      return a < b ? a : b;  }   int main(){    int m, n;    while(scanf("%d%d", &m, &n) != EOF)    {        int value[30] = {0};        int dp[200] = {0};        int i, j;        for(i = 0; i < n; i++)            scanf("%d", &value[i]);        for (i = 1; i <= m; i++)            dp[i] = INF;        for (i = 0; i < n; i++)              for (j = m; j >= value[i]; j--)                  dp[j] = min(dp[j], dp[j-value[i]]+1);            if(dp[m] == INF)            printf("0\n");        else            printf("%d\n", dp[m]);    }    //system("pause");    return 0;}/**************************************************************    Problem: 1209    User: superlc320    Language: C++    Result: Accepted    Time:40 ms    Memory:1020 kb****************************************************************/
0 0