Buggy python submission (verdict: Time Limit Exceeded):
import functools
import threading
import sys


class SearchProblem(object):
    def __init__(self, N, H, K):
        self.N = N
        self.H = H
        self.K = K

    def isEnd(self, i):
        return i == self.N

    def succ(self, i):
        return [
            (i + k, abs(self.H[i + k] - self.H[i]))
            for k in range(1, self.K + 1)
            if i + k <= self.N
        ]


def solve(problem: SearchProblem):
    @functools.lru_cache(maxsize=None)
    def future_cost(s):
        if problem.isEnd(s):
            return 0
        else:
            return min(
                cost + future_cost(next_state) for next_state, cost in problem.succ(s)
            )

    return future_cost(1)


def main():
    N, K = [int(x) for x in input().split(" ")]
    H = [None] + [int(x) for x in input().split(" ")]
    problem = SearchProblem(N, H, K)
    print(solve(problem))


if __name__ == "__main__":

    sys.setrecursionlimit(1024 * 1024 * 2)
    threading.stack_size(128 * 1024 * 1024 * 2)
    threading.Thread(target=main).start()


Fixed submission:
import functools
import threading
import sys


def main():
    @functools.lru_cache(maxsize=None)
    def solve(n):
        if n == 1:
            return 0
        else:
            return min(
                solve(n - k) + abs(H[n] - H[n - k])
                for k in range(1, K + 1)
                if n - k >= 1
            )

    N, K = [int(x) for x in input().split(" ")]
    H = [None] + [int(x) for x in input().split(" ")]
    print(solve(N))


if __name__ == "__main__":

    sys.setrecursionlimit(1024 * 1024 * 2)
    threading.stack_size(128 * 1024 * 1024 * 2)
    threading.Thread(target=main).start()

Buggy python submission (verdict: Time Limit Exceeded):
import functools
import threading
import sys


class SearchProblem(object):
    def __init__(self, N, H, K):
        self.N = N
        self.H = H
        self.K = K

    def isEnd(self, i):
        return i == self.N

    def succ(self, i):
        res = []
        for k in range(1, self.K + 1):
            if i + k <= self.N:
                res.append((i + k, abs(self.H[i + k] - self.H[i])))

        return res


def solve(problem: SearchProblem):
    @functools.lru_cache(maxsize=None)
    def future_cost(s):
        if problem.isEnd(s):
            return 0
        else:
            return min(
                cost + future_cost(next_state) for next_state, cost in problem.succ(s)
            )

    return future_cost(1)


def main():
    N, K = [int(x) for x in input().split(" ")]
    H = [None] + [int(x) for x in input().split(" ")]
    problem = SearchProblem(N, H, K)
    print(solve(problem))


if __name__ == "__main__":

    sys.setrecursionlimit(1024 * 1024 * 2)
    threading.stack_size(128 * 1024 * 1024 * 2)
    threading.Thread(target=main).start()


Fixed submission:
import functools
import threading
import sys


def main():
    @functools.lru_cache(maxsize=None)
    def solve(n):
        if n == 1:
            return 0
        else:
            return min(
                solve(n - k) + abs(H[n] - H[n - k])
                for k in range(1, K + 1)
                if n - k >= 1
            )

    N, K = [int(x) for x in input().split(" ")]
    H = [None] + [int(x) for x in input().split(" ")]
    print(solve(N))


if __name__ == "__main__":

    sys.setrecursionlimit(1024 * 1024 * 2)
    threading.stack_size(128 * 1024 * 1024 * 2)
    threading.Thread(target=main).start()