zoukankan      html  css  js  c++  java
  • UVA 147 Dollars

      这题和UVA 674差不多,都是硬币问题。上次我是抄的,结果还没看懂,这次终于自己写了!本来我已经想好了一种递推,用d[i][j]表示面值为 i 时必须用coin[j]且最大硬币为coin[j]时的总数,那么d[i][j] = d[i-coin[j]][0] + d[i-coin[j]][1] +……+d[i-coin[j]][j],最终结果为d[i][0] + d[i][1] +……+d[i][10],还是要有一个相加的过程,感觉不够利索,只好再重新构造递推关系,令f[i][j]表示面值为 i 时最大硬币为coin[j]时的总数,则f[i][j] = d[i][0] + d[i][1] +……+d[i][j],f的递推关系为:f[i][j] = f[i-coin[j]][0] + f[i-coin[j]][1] +……+f[i-coin[j]][j],看起来很简单,可是我推的时候却绕了老大弯子。最终结果就是f[i][10]了。在此吹下小牛,我感觉我写的比我抄的674那题要好。他的代码如下:

    long dp(long s,long k)
    {
    if(d[s][k]!=-1) return d[s][k];
    d[s][k]=0;
    for(long i=k;i<6 && s>=coin[i];i++)
    d[s][k]+=dp(s-coin[i],i);
    //printf("d[%d][%d]:%d\n",s,k,d[s][k]);
    return d[s][k];
    }

    如果把文中我加的一行输出中间过程的代码加上去,就会发现他的大部分dp[s-coin[i]][i]都是0,这对效率是种浪费。

    这题和674还有些不一样,674数据都是整数,而这题是小数,很容易遇上浮点误差,不过用一些小技巧就能避免这个问题。

    最后,我又花了一些时间来想边界问题,还算可以,只要memset一次就不需要再赋初值了。

     1 #include<stdio.h>
    2 #include<string.h>
    3 typedef long long int llg;
    4 llg f[6010][12];
    5 int coin[] = {1,2,4,10,20,40,100,200,400,1000,2000};
    6 llg dp(int i,int j)
    7 {
    8 llg &ans = f[i][j];
    9 if(ans) return ans;
    10 ans = 1;
    11 for(int k = 1; k <= j && i >= coin[k]; k++)
    12 ans += dp(i-coin[k],k);
    13 return ans;
    14 }
    15 int main()
    16 {
    17 int a,b,sum;
    18 llg ans;
    19 memset(f,0,sizeof(f));
    20 while(scanf("%d.%d",&a,&b)==2)
    21 {
    22 if(!a && !b) break;
    23 sum = a*20 + b/5;
    24 ans = dp(sum,10);
    25 printf("%3d.%d%d%17lld\n",a,b/10,b%10,ans);
    26 }
    27 return 0;
    28 }



  • 相关阅读:
    【iCore、iCore2 双核心板】EPCS 实验(SPI Flash)(基于Verilog语言)
    【iCore2双核心板】SRAM 读写实验(基于Verilog语言)
    大便难案
    乌梅丸案二则
    奔豚
    中医对甲流的认识
    大青龙汤临床应用
    中风之补阳还五汤
    时方的魅力
    艾灸急治
  • 原文地址:https://www.cnblogs.com/lzxskjo/p/2435497.html
Copyright © 2011-2022 走看看