Algorithms
Overpayment
Denominations
Pricing Analysis
Computational Methods

Algorithm possible amounts overpaid for a specific price, based on denominations

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Given a target price and allowed denominations, a common task is to compute all possible overpayment amounts. This appears in cash systems, voucher handling, and optimization of payout strategies. The challenge is not only finding one valid payment, but characterizing the full space of reachable overpay values under clear limits.

Core Sections

1. Formalize the problem and constraints

Define the input first:

  • price: non-negative integer target.
  • denominations: positive integer set, such as one, five, ten.
  • Optional limits, such as maximum number of items used or maximum total paid.

Define output clearly:

  • Sorted unique list of paid - price values where paid is reachable and not smaller than price.
  • Include zero if exact payment is reachable.

Constraints are essential. Without limits, the set of overpay values can be infinite when denomination one exists. Most real systems cap by coin count, note count, or a maximum overpay threshold.

2. Dynamic programming for reachable totals

A practical approach is to compute reachable totals up to an upper bound, then derive overpay values. This is deterministic and easy to explain.

python
1from typing import List, Set
2
3
4def possible_overpay(price: int, denoms: List[int], max_total: int) -> List[int]:
5    reachable: Set[int] = {0}
6    for total in range(max_total + 1):
7        if total not in reachable:
8            continue
9        for d in denoms:
10            nxt = total + d
11            if nxt <= max_total:
12                reachable.add(nxt)
13
14    overpay = sorted(total - price for total in reachable if total >= price)
15    return overpay
16
17
18print(possible_overpay(price=17, denoms=[5, 10], max_total=50)[:10])

This gives all overpay values in the bounded range. The max_total bound should come from domain rules, not from guesswork.

If the system restricts how many pieces may be used, model states as total and count. Breadth-first search is a clean fit because each expansion adds one denomination.

python
1from collections import deque
2
3
4def possible_overpay_limited(price: int, denoms: List[int], max_coins: int) -> List[int]:
5    q = deque([(0, 0)])
6    seen = {(0, 0)}
7    paid = set()
8
9    while q:
10        total, used = q.popleft()
11        if total >= price:
12            paid.add(total)
13        if used == max_coins:
14            continue
15        for d in denoms:
16            nxt = (total + d, used + 1)
17            if nxt not in seen:
18                seen.add(nxt)
19                q.append(nxt)
20
21    return sorted(p - price for p in paid)

This version prevents runaway search while preserving correctness under count limits.

4. Complexity and pruning

For bounded dynamic programming, complexity is roughly proportional to max_total multiplied by number_of_denominations. For count-limited search, complexity depends on branching factor and maximum depth.

Useful pruning ideas:

  • Remove duplicate denominations.
  • Remove denominations larger than the maximum reachable total if exact policy allows.
  • Compute the greatest common divisor of denominations. If price parity conflicts with that divisor, exact payment may be impossible, and overpay starts above zero.

These small checks can reduce work significantly for large datasets.

5. Validation and operational usage

Validation should compare algorithm results with a brute-force reference on small inputs. This catches logic mistakes before scaling up.

Operationally, store metadata with each result set:

  • input denominations
  • bound assumptions
  • whether exact payment exists
  • minimum non-zero overpay

That metadata makes audits easier when payout behavior is questioned later.

Common Pitfalls

  • Forgetting to apply a bound, which can make the search effectively unbounded.
  • Mixing denomination count limits with total-value limits without documenting precedence.
  • Returning duplicate overpay values instead of unique sorted results.
  • Ignoring denomination normalization, causing unnecessary state explosion.
  • Skipping reference checks and trusting complex pruning logic without verification.

Summary

  • Overpay analysis must start from explicit bounds and output rules.
  • Bounded dynamic programming is a strong default for reachable totals.
  • Breadth-first search handles coin-count constraints cleanly.
  • Lightweight pruning can cut runtime without harming correctness.
  • Keep assumptions and metadata with results for auditability and reuse.

Course illustration
Course illustration

All Rights Reserved.