Buggy python submission (verdict: Time Limit Exceeded):
from collections import deque


def bfs(si, sj):
    q = deque()
    used = set()
    if grids[sj][si] == '#':
        q.append([si, sj, 1])
    else:
        q.append([si, sj, 0])

    ans = float('inf')
    while len(q) > 0:
        prv_si, prv_sj, num_b = q.popleft()
        if [prv_si, prv_sj] == [W - 1, H - 1]:
            ans = min(ans, num_b)

        else:
            if prv_si < W - 1:
                if grids[prv_sj][prv_si] == '.' and grids[prv_sj][prv_si + 1] == '#':
                    q.append([prv_si + 1, prv_sj, num_b + 1])
                else:
                    q.append([prv_si + 1, prv_sj, num_b])

            if prv_sj < H - 1:
                if grids[prv_sj][prv_si] == '.' and grids[prv_sj + 1][prv_si] == '#':
                    q.append([prv_si, prv_sj + 1, num_b + 1])
                else:
                    q.append([prv_si, prv_sj + 1, num_b])

    return ans


H, W = map(int, input().split())
grids = [input() for _ in range(H)]
print(bfs(0, 0))


Fixed submission:
H, W = map(int, input().split())
grids = [input() for _ in range(H)]
dp = [[float('inf') for _ in range(W)] for _ in range(H)]
if grids[0][0] == '#':
    dp[0][0] = 1
else:
    dp[0][0] = 0

for i in range(W):
    for j in range(H):
        if i == 0 and j == 0:
            continue

        if i - 1 < 0:
            val1 = float('inf')
        elif grids[j][i - 1] == '.' and grids[j][i] == '#':
            val1 = dp[j][i - 1] + 1
        else:
            val1 = dp[j][i - 1]

        if j - 1 < 0:
            val2 = float('inf')
        elif grids[j - 1][i] == '.' and grids[j][i] == '#':
            val2 = dp[j - 1][i] + 1
        else:
            val2 = dp[j - 1][i]

        dp[j][i] = min(val1, val2)
        #print(i,j,dp)

#print(dp)
print(dp[-1][-1])

Buggy python submission (verdict: Time Limit Exceeded):
from collections import deque


def bfs(si, sj):
    q = deque()
    used = set()
    if grids[sj][si] == '#':
        q.append([si, sj, 1])
    else:
        q.append([si, sj, 0])
    used.add(tuple([si, sj]))

    ans = float('inf')
    while len(q) > 0:
        prv_si, prv_sj, num_b = q.popleft()
        if [prv_si, prv_sj] == [W - 1, H - 1]:
            ans = min(ans, num_b)

        else:
            if prv_si < W - 1:
                if grids[prv_sj][prv_si] == '.' and grids[prv_sj][prv_si + 1] == '#':
                    q.append([prv_si + 1, prv_sj, num_b + 1])
                else:
                    q.append([prv_si + 1, prv_sj, num_b])
                used.add(tuple([prv_si + 1, prv_sj]))

            if prv_sj < H - 1:
                if grids[prv_sj][prv_si] == '.' and grids[prv_sj + 1][prv_si] == '#':
                    q.append([prv_si, prv_sj + 1, num_b + 1])
                else:
                    q.append([prv_si, prv_sj + 1, num_b])
                used.add(tuple([prv_si, prv_sj + 1]))
    return ans


H, W = map(int, input().split())
grids = [input() for _ in range(H)]
print(bfs(0, 0))


Fixed submission:
H, W = map(int, input().split())
grids = [input() for _ in range(H)]
dp = [[float('inf') for _ in range(W)] for _ in range(H)]
if grids[0][0] == '#':
    dp[0][0] = 1
else:
    dp[0][0] = 0

for i in range(W):
    for j in range(H):
        if i == 0 and j == 0:
            continue

        if i - 1 < 0:
            val1 = float('inf')
        elif grids[j][i - 1] == '.' and grids[j][i] == '#':
            val1 = dp[j][i - 1] + 1
        else:
            val1 = dp[j][i - 1]

        if j - 1 < 0:
            val2 = float('inf')
        elif grids[j - 1][i] == '.' and grids[j][i] == '#':
            val2 = dp[j - 1][i] + 1
        else:
            val2 = dp[j - 1][i]

        dp[j][i] = min(val1, val2)
        #print(i,j,dp)

#print(dp)
print(dp[-1][-1])