from typing import List


def calculate_initial_prices(ps_recipes:List[List[int]], max_price_per_category:float)->List[float]:
    """
    Calculate a vector of initial prices such that
       (a) the sum of prices in all recipes is the same
       (b) the price in each category is at most max_price_per_category (a negative number).
    :param ps_recipes:  A list of PS recipes.
    :param max_price_per_category: a negative number indicating the maximum price per category
           (should be smaller than all valuations of traders in this category).
    :return: A vector of initial prices.

    >>> calculate_initial_prices([[1,1,0,0],[1,0,1,1]], -100)
    [-100.0, -200.0, -100.0, -100.0]
    >>> calculate_initial_prices([[1,2,0,0],[1,0,1,2]], -100)
    [-100.0, -150.0, -100.0, -100.0]
    >>> calculate_initial_prices([[1,2,0,0],[1,0,1,3]], -100)
    [-100.0, -200.0, -100.0, -100.0]
    >>> calculate_initial_prices([[2,3,0,0],[2,0,1,3]], -300)
    [-300.0, -400.0, -300.0, -300.0]
    """
    num_recipes = len(ps_recipes)
    num_categories = len(ps_recipes[0])

    # variables: 0 (the sum);  1, ..., num_categories-1 [the prices)
    weighted_depths = []
    price_vector = [float(max_price_per_category)] * num_categories
    for recipe in ps_recipes:
        weighted_depths.append(sum(recipe))
    max_weighted_depth = max(weighted_depths)

    for i in range(len(ps_recipes)):
        recipe = ps_recipes[i]
        for j in range(num_categories - 1, -1, -1):
            if recipe[j] > 0:
                if price_vector[j] != max_price_per_category:
                    raise ValueError("Cannot determine initial prices: "+str(price_vector))
                price_vector[j] = float(max_price_per_category * (max_weighted_depth - weighted_depths[i] + recipe[j])/recipe[j])
                break
    return price_vector