Programmation dynamique
Contents
Programmation dynamique#
def knapsack(c, w, v):
"""
Renvoie la valeur maximum que l'on peut mettre
dans un sac à dos de capacité c.
Le ième objet a pour poids w[i] et valeur v[i].
"""
n = len(w) # nombre d'objets
dp = [[0]*(n + 1) for i in range(c + 1)]
# dp[i][j] = valeur max dans un sac de capacité i
# où j est le nombre d'objets autorisés
for i in range(1, c + 1):
for j in range(1, n + 1):
if w[j - 1] <= i:
x = v[j - 1] + dp[i - w[j - 1]][j - 1]
dp[i][j] = max(dp[i][j - 1], x)
else:
dp[i][j] = dp[i][j - 1]
return dp[c][n]
w = [2, 2, 2, 3, 5, 6, 8]
v = [1, 1, 1, 7, 10, 10, 18]
knapsack(10, w, v)
19
def knapsack2(c, w, v):
n = len(w)
dp = [0]*(c + 1)
for j in range(n):
dp_ = dp[:] # copie de dp
for i in range(c + 1):
if w[j] <= i:
dp[i] = max(dp_[i], v[j] + dp_[i - w[j]])
return dp[-1]
knapsack2(10, w, v)
19
def knapsack_memo(c, w, v):
dp = {}
def aux(i, j):
if i == 0 or j == 0:
return 0
if (i, j) not in dp:
dp[(i, j)] = aux(i, j - 1)
if w[j - 1] <= i:
dp[(i, j)] = max(dp[(i, j)], v[j - 1] + aux(i - w[j - 1], j - 1))
return dp[(i, j)]
return aux(c, len(w))
knapsack_memo(10, w, v)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [2], line 13
10 return dp[(i, j)]
11 return aux(c, len(w))
---> 13 knapsack_memo(10, w, v)
NameError: name 'w' is not defined
from functools import cache
def knapsack_memo2(c, w, v):
@cache
def aux(i, j):
if i == 0 or j == 0:
return 0
v = aux(i, j - 1)
if w[j - 1] <= i:
v = max(v, v[j - 1] + aux(i - w[j - 1], j - 1))
return v
return aux(c, len(w))
knapsack_memo2(10, w, v)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [1], line 14
11 return v
12 return aux(c, len(w))
---> 14 knapsack_memo2(10, w, v)
NameError: name 'w' is not defined
Plus courts chemins#
\[\begin{split}M =
\begin{pmatrix}
0 & 3 & 8 & \infty & -4\\
\infty & 0 & \infty & 1 & 7\\
\infty & 4 & 0 & \infty & \infty\\
2 & \infty & -5 & 0 & \infty\\
\infty & \infty & \infty & 6 & 0\\
\end{pmatrix}
\end{split}\]
g = [
[0, 3, 8, float("inf"), -4],
[float("inf"), 0, float("inf"), 1, 7],
[float("inf"), 4, 0, float("inf"), float("inf")],
[2, float("inf"), -5, 0, float("inf")],
[float("inf"), float("inf"), float("inf"), 6, 0]
]
g
[[0, 3, 8, inf, -4],
[inf, 0, inf, 1, 7],
[inf, 4, 0, inf, inf],
[2, inf, -5, 0, inf],
[inf, inf, inf, 6, 0]]
Bellman-Ford#
def bellman(g, r):
n = len(g)
dist = [float("inf") for i in range(n)]
dist[r] = 0
for k in range(n - 2):
for u in range(n):
for v in range(len(g[u])):
if g[u][v] != 0:
dist[v] = min(dist[v], dist[u] + g[u][v])
return dist
bellman(g, 0)
[0, 1, -3, 2, -4]
Floyd-Warshall#
import copy
def floydwarshall(g):
n = len(g)
dist = copy.deepcopy(g)
for k in range(n):
for u in range(n):
for v in range(n):
dist[u][v] = min(dist[u][v], dist[u][k] + dist[k][v])
return dist
floydwarshall(g)
[[0, 1, -3, 2, -4],
[3, 0, -4, 1, -1],
[7, 4, 0, 5, 3],
[2, -1, -5, 0, -2],
[8, 5, 1, 6, 0]]