Как можно решить эту проблему с помощью динамического программирования? - PullRequest
1 голос
/ 10 мая 2019

Инструкции : крыса может двигаться только вверх или вправо

ввод

  • Первая строка содержит номер таблицы размера n и количество сыра m.
  • Со следующей строки указывается позиция x, y сыра

Выход:

  • Максимальное количество сыра для еды

Exemple1:

  • ввод: 1 1 1
  • вывод: 1 1

Example2:

  • ввод:
3 2
1 2
3 1
  • вывод: 1

Пример 3:

  • ввод:
5 5
2 3
3 2
4 3
4 5
5 2
  • вывод: 3

как я могу решить с помощью Python? Я пытался

def maxAverageOfPath(table, N): 
    dp = [[0 for i in range(N)] for j in range(N)] 
    dp[0][0] = table[0][0] 
    # Initialize first column of total table(dp) array 
    for i in range(0, N): 
        dp[i][0] = 0


    for j in range(0, N): 
        dp[0][j] = 0

    for i in range(0, N): 
        for j in range(0, N):
            print(i, j)
            if i == N-1 and j == N-1:
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
                continue
            if i == N-1 :
                dp[i][j] = table[i][j + 1]
                continue

            if j == N-1 :
                dp[i][j] = table[i + 1][j]
                continue
            dp[i][j] = max(table[i + 1][j], table[i][j + 1])

    return dp

но не удалось ...

Ответы [ 2 ]

2 голосов
/ 10 мая 2019

Для динамического программирования вам нужны граничные условия и способ оценить, где вы находитесь сейчас. После этого это более-менее умная грубая сила. Умная часть приходит от запоминания, поэтому вы не повторяете работу.

Вот базовый рекурсивный подход для Python, который делает следующее:

  • Организовать стол сыра в виде замороженного набора кортежей. Это можно хешировать для запоминания, и вы можете определить местоположение в наборе в постоянное время.

  • Создает условие ребра для конца (когда обе координаты равны N) и условие ребра, когда вы уходите с карты - это просто возвращает 0.

  • Использует lru_cache для запоминания. Вы можете легко реализовать это самостоятельно.


from functools import lru_cache

def hasCheese(table, location):
    ''' Helper function just to improve readability '''
    return 1 if location in table else 0

@lru_cache()
def maxC(table, N, location = (0, 0)):  

    # edge conditions final square and off the grid:  
    if location[0] == N and location[1] == N:
        return hasCheese(table, location)
    if any(l > N for l in location):
        return 0

    # recursion
    score_here = hasCheese(table, location)
    return max(score_here + maxC(table, N, (location[0] + 1, location[1])),
               score_here + maxC(table, N, (location[0], location[1] + 1))
              )

t = frozenset([(2, 3), (3, 2), (4, 3), (4, 5), (5, 2)])
N = 5

print(maxC(t, N))
# prints 3

Если вы хотите сделать это сверху вниз, используя матрицу, вам нужно быть очень осторожным, чтобы у вас всегда был предыдущий набор индексов. Делать ошибки таким способом легче, потому что вам нужно правильно настроить индексы и порядок. Когда вы устанавливаете его как два вложенных увеличивающихся цикла, это означает, что следующим значением всегда будет текущая ячейка плюс максимум двух ячеек на единицу меньше - вы всегда должны смотреть назад в матрицу. Непонятно, что вы пытаетесь сделать, когда с нетерпением ждете этого:

 dp[i][j] = table[i][j + 1]

, поскольку j+1 еще не определено.

Так как координаты сыра индексируются 1, простой путь вперед - сделать вашу матрицу индексированной с нулем и размером N + 1. Затем, когда вы запускаете свои циклы for в 1, вы всегда можете посмотреть и на более низкий индекс, не используя матрицу ниже, и избегать большой логики if/else. Например:

def hasCheese(table, location):
    ''' Helper function just to improve readability '''
    return 1 if location in table else 0

def maxAverageOfPath(table, N): 
    # matrix is sized one unit bigger
    dp = [[0 for i in range(N+1)] for j in range(N+1)] 

    # iterate 1-5 inclusive
    for i in range(1, N+1): 
        for j in range(1, N+1):
            # because the zeroth row and column are already zero, this works without undershooting the table
            dp[i][j] = hasCheese(table, (i, j)) + max(dp[i][j-1], dp[i-1][j])
    # solution is in the corner
    return dp[N][N]

t = {(2, 3), (3, 2), (4, 3), (4, 5), (5, 2)}
N  = 5

print(maxAverageOfPath(t, N)) #3

Когда вы закончите, ваша матрица будет выглядеть так:

[0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 1, 1]
[0, 0, 1, 1, 1, 1]
[0, 0, 1, 2, 2, 3]
[0, 0, 2, 2, 2, 3]

Ваша начальная точка в (1, 1) начинается в верхнем правом углу, а ваш ответ - в левом нижнем углу.

1 голос
/ 10 мая 2019

В каждой точке у вас есть два варианта, чтобы двигаться дальше:

  1. массив [строка] [столб + 1]
  2. массив [строка + 1] [столбец]

Как мы должны найти путь, который включает в себя максимальное количество сыра. Это может быть достигнуто путем повторения через массив, как показано ниже для решения того же:

Решение =>

array [i] [j] + Max(Recur(array [i] [j+1]), Recur(array [i+1] [j]));
...