题目大意:给出要买可乐的数量, 以及1元,5元和10元硬币的数量, 每瓶可乐8元,每次照钱会按照最少硬币的方式找回, 问如何投币可使得投入的硬币数最少, 输出最少硬币值。
解题思路:记忆化搜索, 因为可乐每购买一次便要找会硬币,所以对与每个状态考虑的情况比并不是很多。
注意:1、每够买一次可乐便会找回一次硬币,所以不用考虑的太复杂。
2、题目中虽然说1元不超过500个,但是开的记录数组一定要比500大,大约700左右,因为要考虑找回金额的情况。
#include <cstdio> #include <cstring> #include <algorithm> #include <climits> using namespace std; int DP[800][200][100]; int solve(int n, int a, int b, int c) { if (n == 0) return 0; if (DP[a][b][c] != -1) return DP[a][b][c]; DP[a][b][c] = INT_MAX; if (c >= 1) DP[a][b][c] = min(DP[a][b][c], solve(n-1, a+2, b, c-1) + 1); if (a >= 3 && b >= 1) DP[a][b][c] = min(DP[a][b][c], solve(n-1, a-3, b-1, c) + 4); if (a >= 3 && c >= 1) DP[a][b][c] = min(DP[a][b][c], solve(n-1, a-3, b+1, c-1) + 4); if (b >= 2) DP[a][b][c] = min(DP[a][b][c], solve(n-1, a+2, b-2, c) + 2); if (a >= 8) DP[a][b][c] = min(DP[a][b][c], solve(n-1, a-8, b, c) + 8); return DP[a][b][c]; } int main() { int T; scanf("%d", &T); while (T--) { int n, a, b, c; scanf("%d%d%d%d", &n, &a, &b, &c); memset(DP, -1, sizeof(DP)); DP[0][0][0] = 0; printf("%d\n", solve(n, a, b, c)); } return 0; }