NIT-OJ-1449-最少硬币问题-解题报告

来源:互联网 发布:linux下oracle启动 编辑:程序博客网 时间:2024/06/09 08:03
问题描述:
设有n种不同面值的硬币,各硬币的面值存于数组T[1:n]中。现要用这些面值的硬币来
找钱。可以使用的各种面值的硬币个数存于数组Coins[1:n]中。
对任意钱数0≤m≤20001,设计一个用最少硬币找钱m的方法。
算法设计:
对于给定的1≤n≤10,硬币面值数组T和可以使用的各种面值的硬币个数数组Coins,以
及钱数m,0≤m≤20001,计算找钱m的最少硬币数。
数据输入:
输入的第一行中只有1 个整数给出n的值,第2 行起每
行2 个数,分别是T[j]和Coins[j]。最后1 行是要找的钱数m。
结果输出:
将计算出的最少硬币数输出,问题无解时输出-1。
Sample input
3
1 3
2 3
5 3
18
Sample output
5

根据这个题意,就是从这么多个硬币中选最少符合条件的硬币个数。对这种题目我没什么想法,因为DP学的也不是很好,在这里写一下我的实现,仅给各位做一个参考。
我的理解:
1.先看题目输入数据的限制条件,只有n和m有限制,那我就做一个20002的数组存 DP过程中 的值。
2.硬币个数是有限的,那我就把这些硬币看成一个个的而不是一堆堆的。
我的实现过程:

结构体数组存硬币面额和对应的数量
struct Coine
{
int Coin;
int Count;
}g_nInputList[MAX];

DP中间过程的表 int g_nDPList[MAX]
输入的硬币面值种类int g_nInputCoinN
输入的要找的钱的值int  g_nNeedCoin

输入函数即可如下表示
void ProcInput()
{
    int i = g_nInputCoinN;
    while (i--)
    {
         scanf("%d %d", &g_nInputList.Coin, &g_nInputList.Count);
    }
    scanf("%d", &g_nNeedCoin);
}

DP的实现:
总共的硬币个数,每个硬币一个循环,第一个硬币的时候初始化  g_nDPList[0] = 1;作为起始条件。
第一个硬币的时候从数组的尾部开始向前递增,遇到大于 0 的g_nDPList 时候把这个第i个数加上这个硬币的值 存为 TempSUM 再判断g_nDPList[TempSUM] 是否越界,超过g_nNeedCoin 的直接舍弃,否则 再判断g_nDPList[TempSUM]  是否为 0,若为0则直接赋值为g_nDPList[TempSUM] = 1,否则判断g_nDPList[TempSUM] 值是否大于g_nDPList + 1 ,若是则表示能用 g_nDPList + 1 个硬币表示 i 这个值,所以赋值为:g_nDPList[TempSUM] = g_nDPList + 1。否则就舍弃。这样把每个硬币一个这样的循环做完就可以知道能否表示  g_nNeedCoin 这个值了。
实现过程:
void GetResoult()  
{  
   int i = g_nInputCoinN;
   memset(g_nDPList, 0, sizeof(g_nDPList));
   g_nDPList[0]=1;
   while (i--)
   {
    while (g_nInputList.Count--)
    {
     int j = g_nNeedCoin + 1;
     while(j--)
     {
      if(g_nDPList[j] > 0 && (g_nInputList.Coin + j) <= g_nNeedCoin)
      {
       if (0 == g_nDPList[g_nInputList.Coin + j] ||
      g_nDPList[g_nInputList.Coin + j] > (g_nDPList[j] + 1))
       {
      g_nDPList[g_nInputList.Coin + j] = (g_nDPList[j] + 1);
       }
      }
     }
       }
   }
}  

注意,因为是 g_nDPList[0] = 1 这样的初始条件,所以每个值所能表示的最少硬币数其实应该是 g_nDPList - 1 个,所以这样就方便了我们输出的编写。如果不能表示,则 g_nDPList[g_nNeedCoin] 应该是 0,如果可以表示,则至少是1 以上。所以输出就可以这样写了:
void ProcOutput()
{
    printf("%d/n",g_nDPList[g_nNeedCoin] - 1);
}

Run IDSubmit timeJudge StatusProblem IDLanguageRun timeMemory
797762009-02-02 18:38:06Accepted 1449 C 190MS304K