• hdu acm 2844 Coins 解题报告


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2844

    题目意思:有A1,A2,...,An 这 n 种面值的钱,分别对应的数量是C1,C2,...,Cn。问根据这么多数量的钱 能组成多少个 <= m 的钱。

          如果用多重背包来做,超时了...如果用记忆化搜索,还是...超时= =.....

          这个方法是网上搜的,觉得好神奇,能看懂一些。

          它是根据完全背包的思路做的,但是需要限制每种币种的使用数量,于是就多了个used[] 数组来记录了。 ! f[j]表示之前没有组成 j 这么多的钱,f[j] = 1 就表示已经组成过 j 那么多的钱了,下次再遇到同样能构成 j 那么多的钱就不要再重复算了。 这个f[j-A[i]]用得好巧妙,妙在它 j - A[i] 是绝对比 j 小的,如果在不超过C[i] 数量(used[j-A[i]])的情况下,用一定数量的 A[i] 再加上之前用过的 A[i-1] ,A[i-2],...,A[1] (当然也可以不用,也可以用部分) 这些币值能能够组成 j 这么多钱。

          这句:used[j] = used[j-A[i]] + 1;  有一点不太懂,不知道为什么要从used[j-A[i]] 前提下 +1......  

         代码中注释部分可能有误导别人的成分,欢迎指出不足(哎~~~没办法啦,网上的这份代码,好像没有人写过注释,我也是按自己理解啦= =)

          

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 
     6 const int maxn = 1e5 + 5;
     7 const int N = 100 + 5;
     8 
     9 int A[N], C[N];
    10 int f[maxn], used[maxn];
    11 
    12 int main()
    13 {
    14     int n, m;
    15     while (scanf("%d%d", &n, &m) != EOF && (m+n))
    16     {
    17         memset(f, 0, sizeof(f));
    18         for (int i = 0; i < n; i++)
    19             scanf("%d", &A[i]);
    20         for (int i = 0; i < n; i++)
    21             scanf("%d", &C[i]);
    22         f[0] = 1;
    23         int ans = 0;
    24         for (int i = 0; i < n; i++)
    25         {
    26             for (int j = 0; j <= m; j++)
    27                 used[j] = 0;    // used[j]表示当前这种面值为j时用了A[i]多少次,它的使用时限制A[i]被使用的数量,否则就可以用无限个了
    28             for (int j = A[i]; j <= m; j++)
    29             {
    30                 if (!f[j] && f[j-A[i]] && used[j-A[i]] < C[i])  // 用f[j]表示能组成这价值为j的钱和不能(0与1), f[j-A[i]] 表示之前能组成j-A[i]这么多钱
    31                 {
    32                 // printf("!f[j]: !f[%d];  f[j-A[i]]: f[%d]
    ", j, j-A[i]);
    33                 //    printf("used[j-A[i]]: used[%d] = %d, C[i]: C[%d] = %d
    ", j-A[i], used[j-A[i]], i, C[i]);
    34                     f[j] = 1;
    35                     used[j] = used[j-A[i]] + 1;  // 组成j这么多钱还需要用多一次A[i]这样的币值
    36                     ans++;
    37                 //    printf("used[%d] = %d
    ", j, used[j]);
    38                 //    printf("组成面值为 %d 时用了 A[%d](即 %d) %d 次
    
    ", j, i, A[i], used[j]);
    39                 }
    40             }
    41         }
    42         printf("%d
    ", ans);
    43     }
    44     return 0;
    45 }

        输出变量图,真诚奉献,真心强大啊~~~

        

       

  • 相关阅读:
    修改 MyEclipse 中的 jsp 和 servlet 模板
    javaWeb 数据库连接池连接数据库
    发现一个类的方法不够用时,可以使用的3种方法可以增强
    使用 greenDao 框架 操作数据库
    Android之使用Volley框架在ListView中加载大量图片
    js日期选择控件
    mysql 乱码问题
    java 使用反射技术解耦
    javaWeb 使用jsp开发 html过滤标签
    javaWeb 使用jsp开发 foreach 标签
  • 原文地址:https://www.cnblogs.com/windysai/p/3888329.html
Copyright © 2020-2023  润新知