Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python programs on Dynamic Programming #50

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
def count_paths(grid):
m, n = len(grid), len(grid[0])

# Create a 2D dp array to store the number of paths to each cell
dp = [[0] * n for _ in range(m)]

# Initialize the starting position if it's not a hole
if grid[0][0] == 0:
dp[0][0] = 1

# Fill the dp table
for i in range(m):
for j in range(n):
# If the cell is a hole, skip it
if grid[i][j] == 1:
dp[i][j] = 0
else:
# Add the number of paths from the top cell if it exists
if i > 0:
dp[i][j] += dp[i - 1][j]
# Add the number of paths from the left cell if it exists
if j > 0:
dp[i][j] += dp[i][j - 1]

# The answer is the number of paths to the bottom-right cell
return dp[m - 1][n - 1]

# Example usage:
# 0 represents an open cell and 1 represents a hole
grid = [
[0, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 0],
[0, 0, 1, 0]
]
print("Number of paths:", count_paths(grid))
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
def count_paths(grid):
m, n = len(grid), len(grid[0])

# Memoization table
memo = [[-1] * n for _ in range(m)]

# Helper function to calculate paths using DP with memoization
def dp(x, y):
# If out of bounds or if the cell is a hole, return 0 paths
if x < 0 or y < 0 or grid[x][y] == 1:
return 0
# If we are at the start, return 1 path
if x == 0 and y == 0:
return 1
# If already computed, return the cached result
if memo[x][y] != -1:
return memo[x][y]

# Calculate the number of paths from the top and left cells
paths_from_top = dp(x - 1, y)
paths_from_left = dp(x, y - 1)

# Store the result in the memo table and return
memo[x][y] = paths_from_top + paths_from_left
return memo[x][y]

# Start the recursion from the bottom-right cell
return dp(m - 1, n - 1)

# Example usage:
# 0 represents an open cell and 1 represents a hole
grid = [
[0, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 0],
[0, 0, 1, 0]
]
print("Number of paths:", count_paths(grid))
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# https://atcoder.jp/contests/dp/tasks/dp_f

s = input()
t = input()

dp = [[-1] * (len(t) + 1) for _ in range(len(s) + 1)]

# Base check
dp[0] = [0]*(len(t) + 1)
for i in range(len(s)+1):
dp[i][0]=0

for i1 in range(1,len(s)+1):
for i2 in range(1,len(t)+1):
if s[i1 - 1] == t[i2 - 1]: # Take the character
dp[i1][i2] = 1 + dp[i1 - 1][i2 - 1]

else: # Remove one character from s and t successively and compare
dp[i1][i2] = max(dp[i1][i2-1],dp[i1-1][i2])

lcs = dp[len(s)][len(t)] # Lenght of longest common subsequence
# print(lcs)

ans = [] # Find the longest common subsequence
i = len(s)
j = len(t)
while (i > 0 and j > 0):
if (s[i - 1] == t[j - 1]):
ans.append(s[i - 1])
i-=1
j-=1
elif (dp[i - 1][j] < dp[i][j - 1]):
j-=1
else:
i-=1

print(''.join(ans[::-1]))

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Question Link: https://atcoder.jp/contests/dp/tasks/dp_f

s = input()
t = input()

dp = [[-1] * (len(t) + 1) for _ in range(len(s) + 1)]

def func(i1, i2):
# Base check
if i1 == 0 or i2 == 0:
return 0

# Memoization check
if dp[i1][i2] != -1:
return dp[i1][i2]

if s[i1 - 1] == t[i2 - 1]: # Take the character
dp[i1][i2] = 1 + func(i1 - 1, i2 - 1)
return dp[i1][i2]
else: # Remove one character from s and t successively and compare
dp[i1][i2] = max(func(i1, i2 - 1), func(i1 - 1, i2))
return dp[i1][i2]

lcs = func(len(s), len(t)) # Length of longest common subsequence

ans = [] # Find the longest common subsequence
i = len(s)
j = len(t)
while (i > 0 and j > 0):
if (s[i - 1] == t[j - 1]):
ans.append(s[i - 1])
i-=1
j-=1
elif (dp[i - 1][j] < dp[i][j - 1]):
j-=1
else:
i-=1

print(''.join(ans[::-1]))
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Question Link: https://www.geeksforgeeks.org/problems/longest-common-substring1452/1

from typing import List

def longestCommonSubstr(S1: str, S2: str, n: int, m: int) -> int:
dp: List[List[int]] = [[[-1]] * (m + 1) for _ in range(n + 1)]

for i in range(n+1):
dp[i][0] = 0
for i in range(m+1):
dp[0][i] = 0

for i in range(1,n+1):
for j in range(1,m+1):
if S1[i-1] == S2[j-1]:
dp[i][j] = dp[i-1][j-1]+1
else:
dp[i][j]=0

return max(max(dp,key=max))


if __name__ == "__main__":
print(longestCommonSubstr("abacd", "acaba", 5, 5))
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Question Link: https://www.geeksforgeeks.org/problems/longest-common-substring1452/1

from typing import List

def longestCommonSubstr(S1: str, S2: str, n: int, m: int) -> int:
dp: List[List[List[int]]] = [[[-1 for _ in range(2)]] * (m + 1) for _ in range(n + 1)]
ans = func(S1, S2, 1, 1, dp)
return max(ans)

def func(s1: str, s2: str, i: int, j: int, dp: List[List[List[int]]]) -> int:
if i > len(s1) or j > len(s2):
return (0, 0)

if dp[i][j][1] != -1:
return dp[i][j]

a1 = max(func(s1, s2, i, j + 1, dp))
a1 = max(a1, max(func(s1, s2, i + 1, j, dp)))
a2 = [0,-1]
if s1[i - 1] == s2[j - 1]:
a2 = func(s1, s2, i + 1, j + 1, dp)

res = [max(a1, a2[0]), a2[1] + 1]
dp[i][j] = res
return dp[i][j]


if __name__ == "__main__":
print(longestCommonSubstr("abacd", "acaba", 5, 5))
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
n = int(input("Enter number: "))

if n<=1 :
print(n)
exit(1)

dp = [-1]*(n+1) # Creation of DP array
dp[0] = 0 # Base cases
dp[1] = 1

for i in range(2,n+1):
dp[i] = dp[i-1] +dp[i-2] # Recurrence relation

print(dp[n])
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
n = int(input("Enter number: "))

dp = [-1]*(n+1) # Creation of DP array
dp[0] = 0 # Base case

def fib(n):
"""
Calculates the nth Fibonacci number using dynamic programming with memoization.
Parameters:
n (int): The index of the Fibonacci number to calculate.
Returns:
int: The nth Fibonacci number.
"""
# Base case
if n == 0:
return 0
if n == 1:
dp[1] = 1
return 1

# Memoization check
if dp[n] != -1:
return dp[n]

# Recurrence relation
dp[n] = fib(n-1) + fib(n-2)
return dp[n]

print(fib(n))
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Question link: https://atcoder.jp/contests/dp/tasks/dp_d

from typing import List

n, w = map(int, input().split())
weight = [0] * n
price = [0] * n

for i in range(n):
weight[i], price[i] = map(int, input().split())

dp = [[-1] * (w + 1) for _ in range(n + 1)]

# Base case
for j in range(w + 1):
dp[0][j] = 0

for i in range(1, n + 1):
for j in range(w + 1):

# Don't Take current item
dp[i][j] = dp[i - 1][j]

# Take current item
if j - weight[i - 1] >= 0:
dp[i][j] = max(dp[i][j], dp[i - 1][j - weight[i - 1]] + price[i - 1])

print(dp[n][w])

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Question link: https://atcoder.jp/contests/dp/tasks/dp_d

from typing import List

n, w = map(int, input().split())
weight = [0] * n
price = [0] * n

for i in range(n):
weight[i], price[i] = map(int, input().split())

dp = [[-1] * (w + 1) for _ in range(n + 1)]

def func(weight: List[int], price: List[int], idx: int, cur: int) -> int:
if idx == 0:
return 0

if dp[idx][cur] != -1:
return dp[idx][cur]

# Not take
ans = func(weight, price, idx - 1, cur)

# Take
if cur - weight[idx-1] >= 0:
ans = max(ans, func(weight, price, idx - 1, cur - weight[idx-1]) + price[idx-1])

dp[idx][cur] = ans
return ans

print(func(weight, price, n, w))

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Question link: https://www.geeksforgeeks.org/problems/matrix-chain-multiplication0303/1

def matrix_chain_order(arr):
# Number of matrices
n = len(arr) - 1

# Create a 2D array to store the minimum number of multiplications needed to compute the matrix A[i]...A[j]
dp = [[0] * n for _ in range(n)]

# l is the chain length
for l in range(2, n + 1):
for i in range(n - l + 1):
j = i + l - 1
dp[i][j] = float('inf')
for k in range(i, j):
ans = dp[i][k] + dp[k + 1][j] + arr[i] * arr[k + 1] * arr[j + 1]
if ans < dp[i][j]:
dp[i][j] = ans

return dp[0][n - 1]

# Example usage:
# Matrix dimensions: A1 is 40x20, A2 is 20x30, A3 is 30x10 and A4 is 20x30
arr = [40, 20, 30, 10, 30]

# Optimal value = 26000 [ (A1*(A2*A3))*A4 ]
print("Minimum number of multiplications is", matrix_chain_order(arr))
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Question link: https://www.geeksforgeeks.org/problems/matrix-chain-multiplication0303/1


def matrix_chain_order(arr):
n = len(arr) - 1 # Number of matrix is 1 less than lenth of given matrix
memo = [[None] * n for _ in range(n)]
return dp(0, n - 1, memo)

def dp(i, j, memo):
# Base check
if i == j:
return 0

# Memoization check
if memo[i][j] is not None:
return memo[i][j]

min_cost = float('inf')

# Try placing brackets for each 'k' between (i,j)
for k in range(i, j):
cost = dp(i, k) + dp(k + 1, j) + arr[i] * arr[k + 1] * arr[j + 1]
if cost < min_cost:
min_cost = cost

# Save the result in the memoization table
memo[i][j] = min_cost
return min_cost

# Example usage:
# Matrix dimensions: A1 is 40x20, A2 is 20x30, A3 is 30x10 and A4 is 20x30
arr = [40, 20, 30, 10, 30]

# Optimal value = 26000 [ (A1*(A2*A3))*A4 ]
print("Minimum number of multiplications is", matrix_chain_order(arr))
Loading