UVA - 10626 Buying Coke(记忆化搜索)

题意:

有1, 5, 10三种硬币,分别有n1, n5, n10个,用来买c罐可乐。
每次只能买一罐,并且机器会自动按照用最少的硬币来组合最多的钱来找零。
问最少投入多少硬币,才能买到c罐可乐。(口袋里面的钱一定够买c可乐)

思路:

可以先分成有找零的和没找零的:
1.8个1分的
2.3个1分的和1个5分的
3.2个5分的找回2个1分的
4.一个10分的找回2个1分的
5.3个1分的和1个10分的找回1个5分的。
其余的可能也有,但一定不会比上面五种决策更优。
根据以上5种情况,开辟三维数组记忆化搜索。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[750][150][100];
const int INF = 0x3f3f3f3f;
int dps(int n,int a,int b,int c) {
    if(n == 0) {
        return dp[a][b][c] = 0;
    }else if(dp[a][b][c] != INF) {
        return dp[a][b][c];
    }
    if(c >= 1)
        dp[a][b][c] = min(dp[a][b][c], dps(n-1,a+2,b,c-1) + 1);
    if(a >= 3 && b >= 1)
        dp[a][b][c] = min(dp[a][b][c], dps(n-1,a-3,b-1,c) + 4);
    if(a >= 3 && c >= 1)
        dp[a][b][c] = min(dp[a][b][c], dps(n-1,a-3,b+1,c-1) + 4);
    if(b >= 2)
        dp[a][b][c] = min(dp[a][b][c], dps(n-1,a+2,b-2,c) + 2);
    if(a >= 8)
        dp[a][b][c] = min(dp[a][b][c], dps(n-1,a-8,b,c) + 8);
    return dp[a][b][c];
}
int main() {
    int T;
    int n,a,b,c;
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d%d%d",&n,&a,&b,&c);
        memset(dp,INF,sizeof(dp));
        printf("%d\n", dps(n,a,b,c));
    }
    return 0;
}

你可能感兴趣的:(uva,10626)