uva 10626 Buying Coke (DP记忆化搜索)

uva 10626 Buying Coke

I often buy Coca-Cola from the vending machine at work. Usually I buy several cokes at once, since my working mates also likes coke. A coke in the vending machine costs 8 Swedish crowns, and the machine accept crowns with the values 1, 5 and 10. As soon as I press the coke button (after having inserted sufficient amount of money), I receive a coke followed by the exchange (if any). The exchange is always given in as few coins as possible (this is uniquely determined by the coin set used). This procedure is repeated until I’ve bought all the cokes I want. Note that I can pick up the coin exchange and use those coins when buying further cokes.

Now, what is the least number of coins I must insert, given the number of cokes I want to buy and the number of coins I have of each value? Please help me solve this problem while I create some harder problems for you. You may assume that the machine won’t run out of coins and that I always have enough coins to buy all the cokes I want.

Input

The first line in the input contains the number of test cases (at most 50). Each case is then given on a line by itself. A test case consists of four integers: C (the number of cokes I want to buy), n1, n5, n10 (the number of coins of value 1, 5 and 10, respectively). The input limits are 1 <= C <= 150, 0 <= n1 <= 500, 0 <= n5 <= 100 and 0 <= n10 <= 50.

Output

For each test case, output a line containing a single integer: the minimum number of coins needed to insert into the vending machine.

Sample Input

3

2 2 1 1

2 1 4 1

20 200 3 0

Output for Sample

5

3

148

题目大意:有三种硬币1元n1个,5元n5个,10元n10个,要拿去卖n瓶8元的可乐,问如何投币会使得投入的硬币数量最小。

解题思路:每次找回的硬币数量也会是最小的。可以用记忆化搜索做 ,vis[n1][n5][n10]标记当前所剩硬币情况是否出现过,若出现过直接返回dp[n1][n5][n10]

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#define MAX 1<<20
using namespace std;
typedef long long ll;
int vis[700][200][100], dp[700][200][100];
int num, N1, N5, N10;
int DP(int n, int n1, int n5, int n10) {
    if (vis[n1][n5][n10]) {
        return dp[n1][n5][n10];
    } else if (n == 0) {
        vis[n1][n5][n10] = 1;
        dp[n1][n5][n10] = 0;
        return dp[n1][n5][n10];
    } else {
        dp[n1][n5][n10] = MAX;
        if (n1 >= 8) dp[n1][n5][n10] = min(dp[n1][n5][n10], DP(n - 1, n1 - 8, n5,  n10) + 8);
        if (n5 >= 1 && n1 >= 3) dp[n1][n5][n10] = min(dp[n1][n5][n10], DP(n - 1, n1 - 3, n5 - 1, n10) + 4);
        if (n5 >= 2) dp[n1][n5][n10] = min(dp[n1][n5][n10], DP(n - 1, n1 + 2, n5 - 2, n10) + 2);
        if (n10 >= 1) dp[n1][n5][n10] = min(dp[n1][n5][n10], DP(n - 1, n1 + 2, n5, n10 - 1) + 1);
        if (n10 >= 1 && n1 >= 3) dp[n1][n5][n10] = min(dp[n1][n5][n10], DP(n - 1, n1 - 3, n5 + 1, n10 - 1) + 4);
        vis[n1][n5][n10] = 1;
        return dp[n1][n5][n10];
    }
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d %d %d %d", &num, &N1, &N5, &N10);
        memset(vis, 0, sizeof(vis));
        printf("%d\n", DP(num, N1, N5, N10));
    }
    return 0;
}
时间: 2024-10-12 23:15:23

uva 10626 Buying Coke (DP记忆化搜索)的相关文章

uva 10626 Buying Coke (DP + 记忆化搜索)

Problem D Buying Coke Input: Standard Input Output: Standard Output Time Limit: 2 Seconds I often buy Coca-Cola from the vending machine at work. Usually I buy several cokes at once, since my working mates also likes coke. A coke in the vending machi

UVa 10817 (状压DP + 记忆化搜索) Headmaster&#39;s Headache

题意: 一共有s(s ≤ 8)门课程,有m个在职教师,n个求职教师. 每个教师有各自的工资要求,还有他能教授的课程,可以是一门或者多门. 要求在职教师不能辞退,问如何录用应聘者,才能使得每门课只少有两个老师教而且使得总工资最少. 分析: 因为s很小,所以可以用状态压缩. dp(i, s1, s2)表示考虑了前i个人,有一个人教的课程的集合为s1,至少有两个人教的集合为s2. 在递归的过程中,还有个参数s0,表示还没有人教的科目的集合. 其中m0, m1, s0, s1, s2的计算用到位运算,还

UVa 10599【lis dp,记忆化搜索】

UVa 10599 题意: 给出r*c的网格,其中有些格子里面有垃圾,机器人从左上角移动到右下角,只能向右或向下移动.问机器人能清扫最多多少个含有垃圾的格子,有多少中方案,输出其中一种方案的格子编号.格子编号是从 左上角第一个开始,一行一行的按自然数顺序编.起始行列是第一行第一列.所以例如一个格子的行列号为(ro,co),那么它的编号为bh=(ro-1)*column+co,其中column指这个格子有多少列.(我觉得原题里面有个错误,题目叙述倒数第二行应该是41(6,6)不是41(6,7)).

UVa 1252 (状压DP + 记忆化搜索) Twenty Questions

题意: 有n个长为m的各不相同的二进制数(允许存在前导0),别人已经事先想好n个数中的一个数W,你要猜出这个数. 每次只可以询问该数的第K为是否为1. 问采用最优询问策略,则最少需要询问多少次能保证猜到. 比如有1100 和 0110两个数,只需要询问第一或第三位数是否为1,即可猜中,因此答案为1. 分析: d(s, a)表示已经询问了的集合s,在已经询问了的集合中W中为1的集合为a,还需要询问多少次. 如果下一次询问第k位,则询问次数为: 然后取所有k里的最小值即可. 预处理: 对于每个s和a

uva 10123 - No Tipping dp 记忆化搜索

这题的题意是 在双脚天平上有N块东西,依次从上面取走一些,最后使得这个天平保持平衡! 解题: 逆着来依次放入,如果可行那就可以,记得得有木板自身的重量. /************************************************************************* > File Name: 10123.cpp > Author: opas > Mail: [email protected] > Created Time: 2016年10月22日

UVa 1252 - Twenty Questions(记忆化搜索,状态压缩dp)

题目链接:uva 1252 题意: 有n个长度为m的二进制串,每个都是不同的. 为了把所有字符串区分开,你可以询问,每次可以问某位上是0还是1. 问最少提问次数,可以把所有字符串区分开来. 思路来源于:点击打开链接 思路: m很小,可以考虑状态压缩. dp[s1][s2]表示询问的状态为s1时,此时能猜到状态包含s2时最小需要的步数. 当询问的几位=s2的二进制串小于2时就能区分出来了,dp[s1][s2]=0: 不能区分则再询问一次,s1|=(1<<k),如果问某位为0,则s2不变,问某位为

UVA - 10817 Headmaster&#39;s Headache (状压dp+记忆化搜索)

题意:有M个已聘教师,N个候选老师,S个科目,已知每个老师的雇佣费和可教科目,已聘老师必须雇佣,要求每个科目至少两个老师教的情况下,最少的雇佣费用. 分析: 1.为让雇佣费尽可能少,雇佣的老师应教他所能教的所有科目. 2.已聘老师必须选,候选老师可选可不选. 3.dfs(cur, subject1, subject2)---求出在当前已选cur个老师,有一个老师教的科目状态为 subject1,有两个及以上老师教的科目状态为 subject2的情况下,最少的雇佣费用. dp[cur][subje

状压DP+记忆化搜索 UVA 1252 Twenty Questions

题目传送门 1 /* 2 题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来 3 状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1.答案对错集合为s2时,还要问几次才能区分出来 4 若和答案(自己拟定)相差小于等于1时,证说明已经能区分了,回溯.否则还要加问题再询问 5 */ 6 /************************************************ 7 * Author :Running_Time 8 * Created Time :

UVA - 10913Walking on a Grid(记忆化搜索)

题目:Walking on a Grid 题目大意:给出N * N的矩阵,每个格子里都有一个值,现在要求从(1,1)走到(n, n),只能往下,左,右这三个方向走,并且要求最多只能取k个负数,求这样的要求下能得到的走过格子的值之和最大. 解题思路:记忆化搜索,但是这里要四维的,因为要记录方向,为了防止走回头的路,并且取了几个负数也要记录.然后就是dfs了.状态转移方程:dp[x][y][d][k] = dp[x + dir[i][0]][y + dir[i][1]][i][k1] + G[x][