• UVA 10626 Buying Coke


    UVA_10626

        实际上我们注意到硬币的总状态不是很多,约是500*100*50(当然这么说并不准确,后面会再算),所以我们可以把硬币的组合形式看成一个状态。

        剩下的问题就是如何转移状态,我们细算一下,发现花钱的策略不过这么几种,如果再分细一些,可以先分成有找零的和没找零的:①8个1分的;②3个1分的和1个5分的;③2个5分的找回2个1分的;④一个10分的找回2个1分的;⑤3个1分的和1个10分的找回1个5分的。其余的可能也有,但一定不会比上面五种决策更优。

        显然递推是不好搞的,所以就不妨记忆化搜索吧。但注意到,我们按上面的策略花钱时,有些硬币是会增加的,所以我们要把上限算好。首先,③和④会增加1分的数量,最多增加的数量不会超过200个,其次⑤会增加5分的数量,但不会超过50个,于是开个710*160*60的数组即可。

    #include<stdio.h>
    #include<string.h>
    #define INF 1000000000
    int f[710][160][60], C, N, X, Y, Z;
    int dp(int n1, int n5, int n10)
    {
    int i, j, k, min = INF;
    if(f[n1][n5][n10] != -1)
    return f[n1][n5][n10];
    if(n1 + n5 * 5 + n10 * 10 == N)
    return f[n1][n5][n10] = 0;
    if(n1 >= 3 && n5 >= 1)
    {
    k = dp(n1 - 3, n5 - 1, n10);
    if(k + 4 < min)
    min = k + 4;
    }
    if(n5 >= 2)
    {
    k = dp(n1 + 2, n5 - 2, n10);
    if(k + 2 < min)
    min = k + 2;
    }
    if(n1 >= 3 && n10 >= 1)
    {
    k = dp(n1 - 3, n5 + 1, n10 - 1);
    if(k + 4 < min)
    min = k + 4;
    }
    if(n10 >= 1)
    {
    k = dp(n1 + 2, n5, n10 - 1);
    if(k + 1 < min)
    min = k + 1;
    }
    if(n1 >= 8)
    {
    k = dp(n1 - 8, n5, n10);
    if(k + 8 < min)
    min = k + 8;
    }
    return f[n1][n5][n10] = min;
    }
    void solve()
    {
    int res;
    scanf("%d%d%d%d", &C, &X, &Y, &Z);
    N = X + 5 * Y + 10 * Z - C * 8;
    memset(f, -1, sizeof(f));
    res = dp(X, Y, Z);
    printf("%d\n", res);
    }
    int main()
    {
    int t;
    scanf("%d", &t);
    while(t --)
    {
    solve();
    }
    return 0;
    }


  • 相关阅读:
    ***mysql索引总结----mysql索引类型以及创建
    XCODE快捷键个人总结
    ios下划线变量:为什么变量前要加下划线才有用?
    ios开发之AppDelegate
    **IOS:xib文件解析(xib和storyboard的比较,一个轻量级一个重量级)
    NEON简介【转】
    NEON在Android中的使用举例【转】
    时钟频率的理解--笔记【原创】
    理解逐次逼近寄存器型ADC:与其它类型ADC的架构对比【转】
    模数转换器(ADC)的基本原理【转】
  • 原文地址:https://www.cnblogs.com/staginner/p/2277208.html
Copyright © 2020-2023  润新知