これを解決するためにDPは必要ありません。
まず、コインがコモンであると仮定することもできます。なぜなら、そうでなければ、gcdの倍数しか生成できないからです。次にg = gcd(x、y)とし、コインx/gとy/gを使ってceil(B/g)の先端Tを最小化する問題を解く。そして元の問題の解はT * g + g * ceil(B/g) - Bです。
xとy は互いに素である場合、あなたはがを正確に生成することはできません最大数は、xyです - XY。 (https://math.stackexchange.com/questions/66963/largest-integer-that-cant-be-represented-as-a-non-negative-linear-combination-o)
したがって、B> xy-x-yの場合、0チップで正確にお支払いいただけます。
そうでなければ、硬貨xの可能なすべての組み合わせを試して(そして最小の数のyを使用して少なくともBを作る)、ブルートフォースを使って解を見つけることができます。 B < xy以来、それはおおよそyの異なる値です。必要に応じてコインを入れ替えることで、O(min(x、y))時間の最悪の場合の問題を解決できることを意味します。
単一プログラムに一緒にそれを置く:あなたが最初の操作から残りの小さな値と最大値と剰余演算とモジュラス演算を行うことによって溶液を識別することができる
def gcd(x, y):
x, y = min(x, y), max(x, y)
while x != 0:
x, y = y % x, x
return y
def tip(x, y, B):
g = gcd(x, y)
if g != 1:
nB = (B + g - 1) // g
T = tip(x // g, y // g, (B + g - 1) // g)
return T * g + nB * g - B
if B > x * y - x - y:
# We're guaranteed to be able to make B exactly.
return 0
# Swap the coins if necessary so that x is the larger one.
x, y = max(x, y), min(x, y)
T = B
# Try 0, 1, 2, ... B//x+1 of the x coin.
# More than this isn't necessary since (B//x+1)*x
# is already greater than or equal to B.
for i in xrange(B // x + 2):
# j is the smallest number of y coins
# such that ix + jy >= B.
j = max(0, (B - i * x + y - 1) // y)
T = min(T, i * x + j * y - B)
return T
print tip(7, 12, 20)
入力サイズ「B」の制限を知っていますか? – kfx
私は "寛大なティッパーになってください"と言っています:) –