```python
from typing import *
from collections import *

def cut_roll(length: int, board: list[tuple[int, int]]) -> dict:
    if isinstance(length, bool) or not isinstance(length, int) or length < 0:
        raise ValueError("length must be a non-negative whole number")
    
    # Sort boards by price in descending order
    order = sorted(board, key=lambda entry: -entry[1])
    
    # Initialize best and taken arrays
    best = [0] * (length + 1)
    taken = [0] * (length + 1)
    
    # Fill the best array using dynamic programming
    for metres in range(1, length + 1):
        best[metres] = -1
        for piece, price in order:
            if piece <= metres and price + best[metres - piece] > best[metres]:
                best[metres] = price + best[metres - piece]
                taken[metres] = piece
    
    # If no valid cut was found, use the last piece that could fit
    if best[length] == 0:
        for piece in range(1, length + 1):
            if piece <= length and board[piece - 1][0] > 0:
                best[length] = board[piece - 1][1]
                taken[length] = piece
    
    # Collect the pieces used
    pieces: list[int] = []
    while length > 0:
        piece = taken[length]
        if piece > 0:
            pieces.append(piece)
            length -= piece
        else:
            break
    
    return {"takings": best[length], "pieces": pieces[::-1]}
```