가장 칼로리가 많은 식사 준비


9

하루에 5 번 식사를하고 일주일에 7 일이 있기 때문에 한 번에 7 번씩 총 35 번의 레시피를 갖습니다. 각 레시피에는 칼로리가 있습니다. 매일 식사 당 하나의 레시피를 포함해야하며 각 레시피는 특정 식사로 고정됩니다 (예 : 저녁 식사에는 팬케이크를 가질 수 없음). 35 가지 레시피가 모두 솔루션에 있어야하므로 주중에는 레시피를 반복 할 수 없습니다.

매일 가장 많은 칼로리를 섭취 할 수있는 식사를 찾고 싶습니다. 즉, 매일 소비되는 총 칼로리의 차이를 최소화하고 싶습니다.

이것은 숙제 문제가 아니라 실제로 사실입니다! 나는 brute-force보다 더 나은 접근법을 만들 수 없으며 7! ^ 4 조합이 많이 있습니다.


3
나는 이것이 절단 재고 문제 또는 빈 포장 문제 의 변형이라고 생각합니다 .
Doval

명확히하기 위해- "첫날의 식사", "2 번째 식사", 7 번째 "3 차 식사"등 7 가지 레시피가 있습니까? "최종 식사"레시피를 "오늘의 마지막 식사"에 할당 하시겠습니까? (다른 방법으로 저녁 식사를 위해 팬케이크를 제공 하시겠습니까?)
Dan Pichelman

옳은; 당신은하지 않을 것입니다.
dfaulken

2
35 가지 레시피 모두 칼로리 수가 크게 다른 가요? ! 당신이 가장 가까운 10 개 또는 50 칼로리로 칼로리 수를 반올림한다면, 7 ^ 4 쉽게 3이 될 수도 있습니다 ^ 4! - 브 루트 포스를 통해 쉽게 계산할 수 인
댄 Pichelman

2
친구, 당신은 너무 많이 먹고, 하루에 5 번 식사를하면 과체중이됩니다.
Pieter B

답변:


1

문제에 대한보다 공식적인 접근 방법 :

각각 7 개의 숫자로 구성된 5 개의 목록이 있습니다. 각각 5 개의 숫자로 구성된 7 개의 목록을 작성하고 가장 큰 수의 목록과 가장 작은 목록의 차이가 가장 작은 솔루션을 찾으십시오.

휴리스틱이없는 최적의 솔루션을 찾으려면 열거 할 수있는 선택의 여지가 거의 없지만 모든 솔루션을 열거 할 필요는 없습니다.

어떤 해결책을 찾든 "지금까지 가장 잘 찾은"것으로 등록하면 메트릭 관련 성능을 등록하십시오 (최소한 차이라고 생각합니다). 그런 다음 솔루션 분기가 명확하게 벗어난 경우 열거를 중지하십시오. 팁 : 비 건축 일은 남은 모든 식사의 평균 인 최대 칼로리를 갖습니다. 따라서 [10, 2, 2, 1, 1, 0, 0]5 가지 식사 모두 에 대한 목록이 있고 하루 1 일마다 각 식사에 솔루션 10을 작성했다고 가정 해보십시오. 남은 날은 하루 평균 5 칼로리가 될 것이므로 차이는 45 이상이 될 것입니다. 예 max - min = 10를 들어 더 이상 해결책을 찾지 않아도됩니다. 1 일째 다른 메뉴를 직접 시도합니다.


빈 문제가 아닙니다. 빈 문제는 고정 된 수의 빈이 아니며 빈당 고정 된 수의 항목이 아닙니다.
paparazzo

그래, 너가 맞아. 내가 고칠 게
Arthur Havlicek

0

이것은 단지 해킹이지만 닫을 수 있습니다.
단 3 끼만
평균 C #에 이틀 더 가까워지면 기본적으로 식사를 퍼 눕습니다.

더 나은 방법은 Flop에서 boolen을 반환하고 완료 될 때까지 반복하는 것입니다.

플롭이 더 똑똑해질 수 있습니다. 점심과 저녁 식사를 위해 아침 식사를하지 마십시오. 하드 코드 순열이있을 수 있습니다. 이것은 플롭 값이 정렬이 아닌 정렬과 비슷합니다.

public static void MealEven()
{
    List<Day> Days = new List<Day>();
    Random rnd = new Random();
    decimal sum = 0;
    for(int i = 0; i<7; i ++)
    {
        int b = rnd.Next(100) + 40;
        int l = rnd.Next(100) + 60;
        int d = rnd.Next(100) + 80;
        Meal br = new Meal(enumMeal.b, b);
        Meal lu = new Meal(enumMeal.l, l);
        Meal di = new Meal(enumMeal.d, d);
        Day day = new Day(br, lu, di);
        Days.Add(day);
        sum += day.Calories;
    }
    decimal avg = sum / 7;
    foreach (Day d in Days.OrderBy(x => x.Calories))
        System.Diagnostics.Debug.WriteLine(d.Calories);
    System.Diagnostics.Debug.WriteLine("");

    Day low;
    Day high;
    Day lowLast = null;
    Day highLast = null;
    int count = 0;
    while (true)
    {   // first do high and low
        low = Days.OrderBy(x => x.Calories).FirstOrDefault();
        high = Days.OrderByDescending(x => x.Calories).FirstOrDefault();
        if (lowLast != null && lowLast == low && highLast == high)
            break;
        if (count > 1000)
            break;
        lowLast = low;
        highLast = high;
        count++;               
        Flop(ref high, ref low);
    }
    foreach (Day d in Days.OrderBy(x => x.Calories))
        System.Diagnostics.Debug.WriteLine("{0} {1} {2} {3}", d.Calories, d.B.Calories, d.L.Calories, d.D.Calories);
    System.Diagnostics.Debug.WriteLine("");

    // day a one on one pass
    for (int i = 0; i < 7; i ++)
    {
        for (int j = 0; j < 7; j++)
        {
            if (i == j)
                continue;
            Day d1 = Days[i];
            Day d2 = Days[j];
            Flop(ref d1, ref d2);
        }
    }

    foreach (Day d in Days.OrderBy(x => x.Calories))
        System.Diagnostics.Debug.WriteLine("{0} {1} {2} {3}", d.Calories, d.B.Calories, d.L.Calories, d.D.Calories);
    System.Diagnostics.Debug.WriteLine("");
}
public static void Flop (ref Day high, ref Day low)
{
    if(low.Calories > high.Calories)
    {
        int hold = low.B.Calories;
        low.B.Calories = high.B.Calories;
        high.B.Calories = hold;

        hold = low.L.Calories;
        low.L.Calories = high.L.Calories;
        high.L.Calories = hold;

        hold = low.D.Calories;
        low.D.Calories = high.D.Calories;
        high.D.Calories = hold;

    }
    decimal avg = (low.Calories + high.Calories) / (decimal)2;
    int bDiff = (high.B.Calories - low.B.Calories) < 0 ? 0 : (high.B.Calories - low.B.Calories);
    int lDiff = high.L.Calories - low.L.Calories < 0 ? 0 : (high.L.Calories - low.L.Calories);
    int dDiff = high.D.Calories - low.D.Calories < 0 ? 0 : (high.D.Calories - low.D.Calories);
    // only flop is one does not go past the average  
    if (bDiff > 0 && ((low.Calories + bDiff) < avg || (high.Calories - bDiff) > avg))
    {
        int hold = low.B.Calories;
        low.B.Calories = high.B.Calories;
        high.B.Calories = hold;
    }
    if (lDiff > 0 && ((low.Calories + lDiff) < avg || (high.Calories - lDiff) > avg))
    {
        int hold = low.L.Calories;
        low.L.Calories = high.L.Calories;
        high.L.Calories = hold;
    }
    if (dDiff > 0 && ((low.Calories + dDiff) < avg || (high.Calories - dDiff) > avg))
    {
        int hold = low.D.Calories;
        low.D.Calories = high.D.Calories;
        high.D.Calories = hold;
    }
}
public enum enumMeal {b, l, d};
public class Day
{
    public Meal B { get; set; }
    public Meal L { get; set; }
    public Meal D { get; set; }
    public Decimal Calories { get { return (Decimal)(B.Calories + L.Calories + D.Calories); } }
    public Day (Meal b, Meal l, Meal d )
    {
        B = b;
        L = l;
        D = d;
    }
}
public class Meal
{
    public enumMeal Type { get; set; }
    public int  Calories { get; set; }
    public Meal (enumMeal meal, int calories)
    {
        Type = meal;
        Calories = calories;
    }
}   

1
답변을 더 유용하게 / 조명하도록 코드에 설명이나 주석을 추가 할 수있는 방법이 있습니까? 나는 거기에서 무슨 일이 일어나고 있는지 이해하지만 나는 확신 할 수 없다고 생각합니다.
Adam Wells

@AdamWells 몇 가지 의견을 추가했습니다. 너가 이해하지 못한게 뭐야?
paparazzo

플롭으로 클릭하지 않았습니다. 이제 말이 되네요, 고마워요!
Adam Wells

이것이 Java 코드인지조차 알 수 없습니다. 그렇습니까? 죄송합니다. Java 및 Cx 기간이 훨씬 늦었습니다. 어쨌든 메인은 어디에 있습니까?
Arthur Havlicek

@ArthurHavlicek 코드 C #. 그들은 똑같이 보입니다.
paparazzo

0

먼저 식사 당 평균 칼로리 수를 계산하십시오. 그런 다음 하루 평균 평균 색상 수를 계산하십시오. 이것들이 측정 할 수있는 지표가 될 것입니다. 다음으로 식사를 정렬하십시오.

이제 가장 높은 음식과 가장 낮은 음식을 골라보세요. 식사가 같은 시간대에있는 경우 해당 시간대에없는 식사 (저녁 식사 등)를 찾을 때까지 다음 최저 또는 최고로 이동해야합니다. 처음 4 식 (hi / low)에 대해이 작업을 수행하십시오. 다섯 번째 식사에서는 평균에 가장 가까운 식사를 선택하십시오. 다섯 번째 식사를 별도의 버킷에 저장하십시오. 헹구고 7 회 반복하십시오.

이것은 당신의 초기 식사 세트가 될 것입니다. 이것도 꽤 될 것입니다. 최적의 분포를 원한다면 5 번째 식사로 더 세밀하게 조정할 수 있습니다.

다섯 번째 식사 통을 통과하고 며칠 사이에 다섯 번째 식사를 바꾸어 식사가 더 나아지는지 확인하십시오. 여전히 같은 규칙을 적용해야합니다 (한 번에 한 끼 이하의 식사). 좀 더 고르지 않을 수도 있습니다. 이전에 계산 된 평균을 사용하여 개선이 있는지 확인하십시오. 처음 4 개의 식사가 높음 / 낮음을 기준으로 고정되어 있기 때문에 조합이 훨씬 적습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.