• DP:Coins(POJ 1742)


                      

                      用硬币换钱

      题目大意:就是有面值为A1,A2,A3....的硬币,各有C1,C2,C3...的数量,问在钱数为m的范围内,能换多少钱?(不找零)

      这题看名字就知道是完全背包,但是这题又有点不一样,因为这题的硬币数不是无限的,所以我们要用点特殊的思路

      因为这题要我们求的是可以整换的钱的面值数,我们只要保证位置合法就可以了,所以dp矩阵内我们可以以面值数的剩余量为dp量,对于j<面值的位置,我们全部设置为当前面值的硬币数量,当j>=面值时,我们考虑两个位置:1:当上一个位置的这个位置合法(也就i-1面值的剩余硬币数>=0),那我们把dp[i][j]位置设置成当前硬币面值的总数(这个是贪心的思想,我们总是想把钱换更大的面值),

      如果dp[i-1][j]非法,那我们就往dp[i][j-coins[i-1]]的位置考量,如果dp[i][j-coins[i-1]]位置还有硬币剩余,那这个位置就dp[i][j-coins[i-1]]-1就好了,因为我们可以拿多一个硬币换出这个面值。

      然后如果dp[i][j-coins[i-1]]非法,那dp[i][j]这个位置自然也就非法了。

      最后再回头看一下上面的思路,我们发现我们只要一个一维数组就行了,因为对于k<j的位置,我们总是先考虑了,而且dp[i-1][j]我们只使用一次

      最后这题排一次序速度会快一点,数量比较小,直接插入排序就好了,复杂度O(n*m)

      最后吐槽一下自己,这一题wa了好几次,因为我一直把上一个位置考虑错了,本来应该考察dp[i-1][j]的,

       结果变成dp[i-1][j-coins[i-1]]

      

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #define MAX(a,b) (a)>(b)?(a):(b)
     5 
     6 typedef struct coins_set
     7 {
     8     int coins_value;
     9     int coins_sum;
    10 }SET;
    11 
    12 SET coins[101];
    13 int dp[100001];
    14 
    15 void Search(const int, const int);
    16 
    17 void Insertion_Sort(const int n)
    18 {
    19     int i, j, tmp_v, tmp_s;
    20     for (i = 2; i <= n; i++)
    21     {
    22         tmp_v = coins[i].coins_value;
    23         tmp_s = coins[i].coins_sum;
    24         for (j = i; j > 1 && coins[j - 1].coins_value > tmp_v; j--)
    25         {
    26             coins[j].coins_value = coins[j - 1].coins_value;
    27             coins[j].coins_sum = coins[j - 1].coins_sum;
    28         }
    29         coins[j].coins_value = tmp_v;
    30         coins[j].coins_sum = tmp_s;
    31     }
    32 }
    33 
    34 int main(void)
    35 {
    36     int n, m, i;
    37     while (~scanf("%d%d", &n, &m))
    38     {
    39         if (n == 0 && m == 0)
    40             break;
    41         //读取钱的总量
    42         for (i = 1; i <= n; i++)
    43             scanf("%d", &coins[i].coins_value);
    44         for (i = 1; i <= n; i++)
    45             scanf("%d", &coins[i].coins_sum);
    46         Insertion_Sort(n);
    47         Search(n, m);
    48     }
    49     return 0;
    50 }
    51 
    52 void Search(const int n, const int m)
    53 {
    54     int i, j, ans = 0;
    55 
    56     memset(dp, -1, sizeof(dp));
    57     for (i = 1; i <= coins[1].coins_sum; i++)//处理基准状态
    58     {
    59         if (i*coins[1].coins_value <= m)
    60             dp[i*coins[1].coins_value] = coins[1].coins_sum - i;
    61         else break;
    62     }
    63     dp[0] = coins[1].coins_value;
    64     for (i = 2; i <= n; i++)
    65     {
    66         dp[0] = coins[i].coins_value;
    67         for (j = 0; j <= m; j++)
    68         {
    69             if (j - coins[i].coins_value < 0)
    70                 dp[j] = dp[j] == -1 ? -1 : coins[i].coins_sum;
    71             else
    72             {
    73                 if (dp[j] != -1)
    74                     dp[j] = coins[i].coins_sum;
    75                 else if (dp[j - coins[i].coins_value] > -1)
    76                     dp[j] = dp[j - coins[i].coins_value] - 1;
    77                 else
    78                     dp[j] = -1;
    79             }
    80         }
    81     }
    82     for (i = 1; i <= m; i++)
    83         if (dp[i] > -1) ans++;
    84     printf("%d
    ", ans);
    85 }
  • 相关阅读:
    我的学习思维:有关时间的管理
    Eureka的故事,专注能让你看到别人看不到的事情
    善用思维导图来整理发散的思维
    二八原理:人才招聘中的二八原理
    二八原理:员工激励中的二八原理
    二八原理:员工的三种类型
    二八原理:你必须知悉的二八原理
    Java程序员笔试、面试题目
    String StringBuffer StringBuilder
    log4j的使用详细解析
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/4828714.html
Copyright © 2020-2023  润新知