Учитывая стоимость матрицы затрат [] [] и позицию (m, n) в стоимости [] [], напишите функцию, которая возвращает стоимость пути минимальной стоимости для достижения (m, n) из (0, 0). Каждая ячейка матрицы представляет собой стоимость прохождения через эту ячейку. Общая стоимость пути для достижения (m, n) представляет собой сумму всех затрат на этом пути (включая как источник, так и пункт назначения). Вы можете перемещаться только вниз, вправо и по диагонали к нижним ячейкам из данной ячейки, то есть из данной ячейки (i, j), ячеек (i + 1, j), (i, j + 1) и (i + 1, j + 1) можно пройти. Вы можете предположить, что все затраты являются положительными целыми числами.
Например, как показано на следующем рисунке, какова минимальная стоимость пути к (2, 2)?
Путь с минимальной стоимостью выделен на следующем рисунке. Путь (0, 0) -> (0, 1) -> (1, 2) -> (2, 2). Стоимость пути составляет 8 (1 + 2 + 2 + 3).
1) Оптимальная субструктура Путь для достижения (m, n) должен быть через одну из 3 ячеек: (m-1, n-1) или (m-1, n) или (m, n-1). Таким образом, минимальная стоимость для достижения (m, n) может быть записана как «минимум из 3 ячеек плюс стоимость [m] [n]».
minCost (m, n) = min (minCost (m-1, n-1), minCost (m-1, n), minCost (m, n-1)) + стоимость [м] [n]
2) Перекрывающиеся подзадачи Ниже приводится простая рекурсивная реализация проблемы MCP (Minimum Cost Path). Реализация просто следует рекурсивной структуре, упомянутой выше.
С
/ * Наивная рекурсивная реализация проблемы MCP (Minimum Cost Path) * / #include<stdio.h> #include<limits.h> #define R 3 #define C 3
intmin(intx, inty, intz);
/ * Возвращает стоимость пути минимальной стоимости от (0,0) до (m, n) в мате [R] [C] * /
intminCost(intcost[R][C], intm, intn)
{
if(n < 0 || m < 0)
returnINT_MAX;
elseif(m == 0 && n == 0)
returncost[m][n];
else
returncost[m][n] + min( minCost(cost, m-1, n-1),
minCost(cost, m-1, n),
minCost(cost, m, n-1) );
}
/ * Вспомогательная функция, которая возвращает минимум 3 целых числа * /
intmin(intx, inty, intz)
{
if(x < y)
return(x < z)? x : z;
else
return(y < z)? y : z;
}
/ * Программа драйвера для проверки вышеуказанных функций * /
/ * Возвращает стоимость минимума Стоимость пути от (0,0) до (m, n) в мате [R] [C] * /
functionminCost($cost, $m, $n)
{
global$R;
global$C;
if($n< 0 || $m< 0)
returnPHP_INT_MAX;
elseif($m== 0 && $n== 0)
return$cost[$m][$n];
else
return$cost[$m][$n] +
min1(minCost($cost, $m- 1, $n- 1),
minCost($cost, $m- 1, $n),
minCost($cost, $m, $n- 1) );
}
/ * Полезная функция, которая возвращает минимум 3 целых числа * /
functionmin1($x, $y, $z)
{
if($x< $y)
return($x< $z)? $x: $z;
else
return($y< $z)? $y: $z;
}
// Код драйвера
$cost= array(array(1, 2, 3),
array(4, 8, 2),
array(1, 5, 3));
echominCost($cost, 2, 2);
// Этот код предоставлен mits. ?>
Выход:
8
Следует отметить, что вышеуказанная функция снова и снова вычисляет одни и те же подзадачи. Смотрите следующее дерево рекурсии, есть много узлов, которые появляются более одного раза. Временная сложность этого наивного рекурсивного решения является экспоненциальной и очень медленной.
Таким образом, проблема MCP имеет оба свойства (см. Это и это ) задачи динамического программирования. Как и другие типичные проблемы динамического программирования (DP) , повторных вычислений с одинаковыми подзадачами можно избежать, построив временный массив tc [] [] в порядке снизу вверх.
C ++
/ * Динамическое программирование реализации проблемы MCP * / #include<stdio.h> #include<limits.h> #define R 3 #define C 3
intmin(intx, inty, intz);
intminCost(intcost[R][C], intm, intn)
{
inti, j;
// Вместо следующей строки мы можем использовать int tc [m + 1] [n + 1] или
// динамически распределяем память для экономии места. Следующая строка
// используется для упрощения программы и обеспечения ее работы на всех компиляторах.
inttc[R][C];
tc[0][0] = cost[0][0];
/ * Инициализировать первый столбец массива общей стоимости (тс) * /
for(i = 1; i <= m; i++)
tc[i][0] = tc[i-1][0] + cost[i][0];
/ * Инициализировать первую строку массива tc * /
for(j = 1; j <= n; j++)
tc[0][j] = tc[0][j-1] + cost[0][j];
/ * Создаем остаток массива tc * /
for(i = 1; i <= m; i++)
for(j = 1; j <= n; j++)
tc[i][j] = min(tc[i-1][j-1],
tc[i-1][j],
tc[i][j-1]) + cost[i][j];
returntc[m][n];
}
/ * Вспомогательная функция, которая возвращает минимум 3 целых числа * /
intmin(intx, inty, intz)
{
if(x < y)
return(x < z)? x : z;
else
return(y < z)? y : z;
}
/ * Программа драйвера для проверки вышеуказанных функций * /
intmain()
{
intcost[R][C] = { {1, 2, 3},
{4, 8, 2},
{1, 5, 3} };
printf(" %d ", minCost(cost, 2, 2));
return0;
}
Джава
/ * Java-программа для реализации динамического программирования
задачи Min Cost Path * /
importjava.util.*;
classMinimumCostPath
{
/ * Вспомогательная функция, которая возвращает минимум 3 целых числа * /
privatestaticintmin(intx, inty, intz)
{
if(x < y)
return(x < z)? x : z;
else
return(y < z)? y : z;
}
privatestaticintminCost(intcost[][], intm, intn)
{
inti, j;
inttc[][]=newint[m+1][n+1];
tc[0][0] = cost[0][0];
/ * Инициализировать первый столбец массива общей стоимости (тс) * /
for(i = 1; i <= m; i++)
tc[i][0] = tc[i-1][0] + cost[i][0];
/ * Инициализировать первую строку массива tc * /
for(j = 1; j <= n; j++)
tc[0][j] = tc[0][j-1] + cost[0][j];
/ * Создаем остаток массива tc * /
for(i = 1; i <= m; i++)
for(j = 1; j <= n; j++)
tc[i][j] = min(tc[i-1][j-1],
tc[i-1][j],
tc[i][j-1]) + cost[i][j];
returntc[m][n];
}
/ * Программа драйвера для проверки вышеуказанных функций * /
publicstaticvoidmain(String args[])
{
intcost[][]= {{1, 2, 3},
{4, 8, 2},
{1, 5, 3}};
System.out.println(minCost(cost,2,2));
}
} // Этот код предоставлен Панкаджем Кумаром
питон
# Динамическое программирование Python-реализация Min Cost Path # проблема
R =3
C =3
defminCost(cost, m, n):
# Вместо следующей строки мы можем использовать int tc [m + 1] [n + 1] или
# динамически размещать памятки для экономии места. Следующее
# строка используется для упрощения работы программы и обеспечения ее работоспособности
# на всех компиляторах.
tc =[[0forx inrange(C)] forx inrange(R)]
tc[0][0] =cost[0][0]
# Инициализировать первый столбец массива общей стоимости (тс)