House-coloring optimization challenge
I do have a lot of comments, but I find your solution pretty good.  The algorithm makes sense, and your comments make it easy to follow.

The function is closer to a computation than a search, so I wouldn't call it find….  The N parameter is redundant, since it can be deduced from the dimensions of prices.  On the other hand, color_names is hard-coded (and worse, 3 is hard-coded in several places); I would make it parameterized.  The comment on the function should be a docstring.

I would prefer to return a list; the caller can join them into a string if desired.

I can understand crashing if there are 0 colors (because the problem would be ill-defined in that case), but the function should not crash if there are 0 houses.

The algorithm works by "walking up and down the street", evaluating the color choice at each house.  Therefore, the code would be more natural if you transposed the matrices,1 such that the primary axis is the house number, and the secondary axis is the color.  You can observe the benefit when writing the totals for the first house: your solution slices prices; my solution below just copies an element.

You initialize totals to a matrix of 0s and colorings to a list of 3s.  I prefer to allocate empty lists using [None] * n.

You perform set operations on colors.  I prefer to use list comprehensions with an if filter.  I suspect that that the filtered list comprehension should be faster, though your set operations might be easier to understand.

def cheapest_house_coloring(prices, color_names='ROYGBIV'):
    """
    Finds the cheapest way to color a list of N houses using C colors such that
    no two consecutive houses have the same color.

    prices is an N-by-C array containing the price to paint the house n with
    color c.

    color_names is a sequence containing the names of the colors.
    """
    num_houses = len(prices)
    if not num_houses:
        return []
    num_colors = len(prices[0])

    totals = [None] * num_houses
    totals[0] = prices[0][:]

    # After the first house, dynamic programming does its magic.
    # At each step, add the price of painting this house
    # to the minimum of the total painting of the other colors.
    for house in range(1, num_houses):
        totals[house] = [
            prices[house][color] +
            min(totals[house - 1][c] for c in range(num_colors) if c != color)
            for color in range(num_colors)
        ]

    # Now we have the totals to paint up to each house.
    # We'll just work backwards to find the coloring of the houses.
    colorings = [None] * num_houses
    colorings[-1] = min(range(num_colors), key=lambda c: totals[-1][c])
    for house in range(num_houses - 2, -1, -1):
        # Take the index of the cheapest option (infinite cost
        # prohibits consecutive houses with the same color)
        colorings[house] = min(range(num_colors),
            key=lambda c: totals[house][c] if c != colorings[house + 1]
                else float('Infinity'))

    # Convert color indexes to names
    return [color_names[colorings[house]] for house in range(num_houses)]




1 If you need to transpose a matrix, use list(zip(*matrix)).