Logic d需要立即解决的问题

Logic d需要立即解决的问题,logic,Logic,例如,添加一种新成分,每种蛋白质、碳水化合物和脂肪都含有1克。另外再添加3种成分,每种成分都含有1克独特的营养素——一种是1克蛋白质,0碳水化合物/脂肪,一种是1克碳水化合物0克蛋白质/脂肪,等等。在这里,你至少有两种,如果不是很多的话,都能完全符合目标 让我们继续,并且假设蛋白质食物对你来说很重要,所以你宁愿多吃1g/1g/1g的营养素。如果我们不能完全达到目标,但不让你喝15杯牛奶,什么都不喝,我们如何衡量溶液 背包问题是一个很好的开始,但是有一百万种不同的方法可以把这个问题分成不同的部分,

例如,添加一种新成分,每种蛋白质、碳水化合物和脂肪都含有1克。另外再添加3种成分,每种成分都含有1克独特的营养素——一种是1克蛋白质,0碳水化合物/脂肪,一种是1克碳水化合物0克蛋白质/脂肪,等等。在这里,你至少有两种,如果不是很多的话,都能完全符合目标

让我们继续,并且假设蛋白质食物对你来说很重要,所以你宁愿多吃1g/1g/1g的营养素。如果我们不能完全达到目标,但不让你喝15杯牛奶,什么都不喝,我们如何衡量溶液

背包问题是一个很好的开始,但是有一百万种不同的方法可以把这个问题分成不同的部分,如果你想尝试编写一个解决方案,我建议你尝试解决一些特定的问题,然后在你理解了引擎盖下发生的事情后,尝试扩展它

-- Limits by protein/carb/fat
DECLARE @protein_limit INT
SET @protein_limit = 160

DECLARE @carb_limit INT
SET @carb_limit = 90

DECLARE @fat_limit INT
SET @fat_limit = 120



-- Table holding valid items
DECLARE @items TABLE
(
    id INT IDENTITY(1,1),
    name VARCHAR(50),
    protein INT,
    carb INT,
    fat INT
)

INSERT INTO @items
      SELECT 'Bread', 1, 2, 4
UNION SELECT 'Sugar', 3, 6, 1
UNION SELECT 'Coffee', 8, 2, 2
UNION SELECT 'Meat', 7, 0, 12
UNION SELECT 'Milk', 16, 12, 2


DECLARE @item_count INT
SELECT @item_count = COUNT(*)
FROM @items


-- From: http://stackoverflow.com/questions/9507635/pivot-integer-bitwise-values-in-sql/9509598#9509598
DECLARE @bits TABLE
(
    number INT,
    [bit] INT,
    value INT
)


; with AllTheNumbers as (
    select cast (POWER(2, @item_count) as int) - 1 Number
    union all
    select Number - 1
    from AllTheNumbers
    where Number > 0
),
Bits as (
    select @item_count - 1 Bit
    union all
    select  Bit - 1
    from Bits
    where Bit > 0
)
INSERT INTO @bits (number, [bit], value)
select *, case when (Number & cast (POWER(2, Bit) as int)) != 0 then 1 else 0 end
from AllTheNumbers cross join Bits
order by Number, [Bit] desc


-- Table to hold trials - brute force!
DECLARE @trials TABLE
(
    trial_id INT,
    item_id INT,
    item_quantity INT
)


DECLARE @trial_max INT
SET @trial_max = (@protein_limit + @carb_limit + @fat_limit) * (POWER(2, @item_count))

DECLARE @trial_id INT
SET @trial_id = 1

DECLARE @base_quantity INT

WHILE @trial_id <= @trial_max
BEGIN

    SET @base_quantity = FLOOR((@trial_id / POWER(2, @item_count)))

    INSERT INTO @trials (trial_id, item_id, item_quantity)
    SELECT @trial_id + 1 + b.number
        , id
        , @base_quantity + b.value
    FROM @items a
    JOIN @bits b
        ON a.id = b.[bit] + 1



    --UPDATE @trials
    --SET item_quantity = @base_quantity + (@trial_id % item_id)
    --WHERE trial_id = @trial_id

    SET @trial_id = @trial_id + POWER(2, @item_count)

END


-- Get results of each trial
SELECT *
FROM @trials a
JOIN @items b
    ON a.item_id = b.id
ORDER BY a.trial_id

-- Use the trial_id field to reference the results of the previous select
SELECT *
FROM
(
    SELECT trial_id
        , SUM(protein * item_quantity) AS protein_total
        , SUM(carb * item_quantity) AS carb_total
        , SUM(fat * item_quantity) AS fat_total
    FROM @trials a
    JOIN @items b
        ON a.item_id = b.id
    GROUP BY trial_id
) a
WHERE protein_total <= @protein_limit
    AND carb_total <= @carb_limit
    AND fat_total <= @fat_limit
ORDER BY ((@protein_limit - protein_total) + (@carb_limit - carb_total) - (@fat_limit - fat_total)) ASC


-- This last query gets the best fit
SELECT c.name
    , b.item_quantity
FROM
(
    SELECT *
        , ROW_NUMBER() OVER (ORDER BY ((@protein_limit - protein_total) + (@carb_limit - carb_total) - (@fat_limit - fat_total)) ASC) AS rn
    FROM
    (
        SELECT trial_id
            , SUM(protein * item_quantity) AS protein_total
            , SUM(carb * item_quantity) AS carb_total
            , SUM(fat * item_quantity) AS fat_total
        FROM @trials a
        JOIN @items b
            ON a.item_id = b.id
        GROUP BY trial_id
    ) a
    WHERE protein_total <= @protein_limit
        AND carb_total <= @carb_limit
        AND fat_total <= @fat_limit
) a
JOIN @trials b
    ON a.trial_id = b.trial_id
JOIN @items c
    ON b.item_id = c.id
WHERE a.rn = 1