AtCoder Context ABC 104 C Strange Bank(奇怪的银行)---动态规划解法
Posted 伟大不DIAO
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Context ABC 104 C Strange Bank(奇怪的银行)---动态规划解法相关的知识,希望对你有一定的参考价值。
运行要求
运行时间限制: 2sec
内存限制: 1024MB
题目
有一家银行,为了让它的用户不那么容易取到钱,规定,每人每次只能取出如下金额的钱
1块钱
6块钱,6*6=36块钱,6*6*6=216块钱
9块钱,9*9=81块钱,9*9*9=729块钱
请问,要从银行里取出N块钱的话,最少要取多少次钱
规定取出来的钱不能再度存入银行
输入前提条件
1 <= N <= 100000
N为整数
输入
输入都以以下标准从命令行输入
N
输出
取出N块钱所需要取钱的最少次数x
例1
输入
127
输出
4
1块钱, 9块钱, 36(=6*6)块钱, 81(=9*9)块钱,
以上4次取法结束后,总共能够取出127块钱
例2
输入
3
输出
3
1块钱, 1块钱, 1块钱,
以上3次取法结束后,总共能够取出3块钱
例3
输入
44852
输出
16
读懂题目
可以看作一个整数N,要把它用1, 小于N的6的次方数, 小于N的9的次方数做拆分。找出拆分所用次数最少的情况。
解题思路
1. 每一种情况都加以统计,然后算出最小的值,显然是不太可能的。因为N最大值是100000,所以每一种都要统计出来话时间会非常大。
2. 每一个整数 I 都有一个对应的值X, X为取出I的钱所用的取钱次数的最小次数。
比如说I为1的话,那么X = 1 (1次重复取出1)
比如说I为2的话,那么X = 2 (2次重复取出1)
比如说I为3的话,那么X = 3 (3次重复取出1)
比如说I为4的话,那么X = 4 (4次重复取出1)
比如说I为5的话,那么X = 5 (6次重复取出1)
比如说I为6的话,那么X = 1 (1次取出6)
比如说I为7的话,那么X = 2 (取出6,再取出1)
当I为7的时候,有2种取法,
1. 一种是取出1,再处理剩下的6
2. 一种是取出6,再处理剩下的1
第1种取法所需要的数量是1(取出1需要1次) + 1(取出6最少需要1次) = 2 次
第2种的取法所需要的数量是1(取出6需要1次) + 1(取出1最少需要1次)
= 2 次
所以I为7的时候,最后的结果是min(第1种的取法,第2种的取法) = 2
当I为8的时候,有2种取法
1. 一种是取出1,再处理剩下的7
2. 一种是取出6,再处理剩下的2
第1种取法所需要的数量是1(取出1需要1次) + 2(取出7最少需要2次) = 3 次
第2种的取法所需要的数量是6(取出6需要1次) + 2(取出2最少需要2次) = 3 次
所以I为8的时候,最后的结果是min(第1种的取法,第2种的取法) = 3
当I为9的时候,有3种取法
1. 一种是取出1,再处理剩下的8
2. 一种是取出6,再处理剩下的3
3. 一种是取出9,再处理剩下的0
第1种的取法所需要的数量是1(取出1需要1次) + 3(取出8最少需要3次) = 4 次
第2种的取法所需要的数量是1(取出6需要1次) + 3(取出3最少需要3次) = 4 次
第3种的取法所需要的数量是1(取出9需要1次) + 0(取出0最少需要0次) = 4 次
所以I为9的时候,最后的结果是min(第1种的取法,第2种的取法,第3种的取法) = 1
当I为10的时候,有3种取法
1. 一种是取出1,再处理剩下的9
2. 一种是取出6,再处理剩下的4
2. 一种是取出9,再处理剩下的1
第1种的取法所需要的数量是1(取出1需要1次) + 1(取出9最少需要1次)
= 2 次
第2种的取法所需要的数量是1(取出6需要1次) + 4(取出4最少需要4次) = = 5 次
第3种的取法所需要的数量是1(取出9需要1次) + 1(取出1最少需要1次) = 2 次
所以I为9的时候,最后的结果是min(第1种的取法,第2种的取法,第3种的取法) = 2
我们隐约地可以感觉到,可以用递归的方法解决问题,因为对于整数N,拆分的方式的第一步的情况可以筛选出来
例如对于整数37
第1步去掉1的情况,所需要的最小次数是A
第1步去掉6的情况,所需要的最小次数是B
第1步去掉36的情况,所需要的最小次数是C
第1步去掉9的情况,所需要的最小次数是D
最后再求出A,B,C,D的最小值
方法1:用一个函数去求N的最小取钱次数。第1步去掉6的倍数,或者9的倍数,或者1以后,剩下的数的最小取钱次数可以再次套用这个函数。
方法2:还有一个办法就是遍历从1到N,对每一个整数求出其最小的取法。对于1-5的整数i来说,最小的解法是i本身,对于i=6和i=9来说,最小的解法是1
首先把这些已知的信息存在一个数组memo
其他的整数可以根据前面索引为i-1,i-6,i-9等数组的值来进行计算
最后求出memo的最后一项值
这道题的方法还可以参照我之前写的一个爬楼梯的解法
代码
方法1
import sys
sys.setrecursionlimit(20000000)
N = int(input())
memo = [-1 for i in range(110000)]
def calculate(n):
if n == 0:
memo[n] = 0
return 0
if memo[n] != -1:
return memo[n]
res = n
pow6Num = 1
while pow6Num*6 <= n:
pow6Num = pow6Num * 6
res = min(res, calculate(n - pow6Num) + 1)
pow9Num = 1
while pow9Num*9 <= n:
pow9Num = pow9Num * 9
res = min(res, calculate(n - pow9Num) + 1)
memo[n] = int(res)
return int(res)
result = calculate(N)
print(memo[N])
方法2
N = int(input())
def calculate(n):
memo = [0 for i in range(N+1)] # 0-N
for index in range(1,n+1):
pow6 = 6
pow9 = 9
if index < 6:
memo[index] = index
elif index == 6:
memo[index] = 1
elif index == 9:
memo[index] = 1
else:
values = []
while pow6 <= index:
values.append(1 + memo[index - pow6])
pow6 = pow6 * 6
while pow9 <= index:
values.append(1 + memo[index - pow9])
pow9 = pow9 * 9
values.append(1+memo[index-1])
minValue = min(values)
memo[index] = minValue
return memo
result = calculate(N)
print(result[N])
总结
这道题的解法有很多,我会在后续的文章中介绍别的解法
目前最常用的解法就是用动态规划的思想去解决
以上是关于AtCoder Context ABC 104 C Strange Bank(奇怪的银行)---动态规划解法的主要内容,如果未能解决你的问题,请参考以下文章
Atcoder ABC 069 C - 4-adjacent D - Grid Coloring