Buggy python submission (verdict: Time Limit Exceeded):
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, radians
from itertools import accumulate, permutations, combinations, product
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left
from fractions import gcd
from heapq import heappush, heappop
from functools import reduce
import numpy as np
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
def ZIP(n): return zip(*(MAP() for _ in range(n)))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7

def main():
	H, W, K = MAP()
	S = np.array([list(map(int, list(input()))) for _ in range(H)])

	ans = INF
	for x in product([0, 1], repeat=H-1):
		cut = np.sum(x)
		if cut >= ans:
				continue
		if np.any(x):
			lis = np.zeros((H, W+1))
			tmp_lis = np.zeros((W))
			idx = 0
			for i, n in enumerate(x):
				tmp_lis += S[i]
				if n:
					lis[idx][1:] += tmp_lis
					idx += 1
					tmp_lis = np.zeros((W))
					
			if H >= 2:
				tmp_lis += S[-1]
				lis[idx][1:] += tmp_lis
			if np.any(lis>K):
				continue
			lis = lis.cumsum(axis=1)
		else:
			lis = np.sum(S, axis=0)
			tmp = 0
			for n in lis:
				if n > K:
					cut = INF
					break
				tmp += n
				if tmp > K:
					cut += 1
					tmp = n
			ans = ans if ans <= cut else cut
			continue
		idx = 0
		while idx <= W:
			tmp_idx = 1001
			flag = False
			for i in range(len(lis)):
				for j in range(idx, W+1):
					if lis[i][j]-lis[i][idx] > K:  # 1番最初にKを超えるところを探す
						tmp_idx = tmp_idx if tmp_idx <= j else j
						flag = True
			if not flag:
				break
			idx = tmp_idx-1
			cut += 1
			if cut >= ans:
				break
		ans = ans if ans <= cut else cut

	print(ans)

if __name__ == '__main__':
	main()


Fixed submission:
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, radians
from itertools import accumulate, permutations, combinations, product
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left
from fractions import gcd
from heapq import heappush, heappop
from functools import reduce
import numpy as np
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
def ZIP(n): return zip(*(MAP() for _ in range(n)))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7

def main():
	H, W, K = MAP()
	S = np.array([list(map(int, list(input()))) for _ in range(H)])

	ans = INF
	for x in product([0, 1], repeat=H-1):
		cut = np.sum(x)
		if cut >= ans:
				continue
		r = 0
		l = []
		for i in range(H-1):
			if x[i]:
				l.append(np.sum(S[r:i+1, :], axis=0))
				r = i + 1
		l.append(np.sum(S[r:, :], axis=0))
		l = np.array(l)
		if np.max(l) > K:
			continue
		tmp = np.zeros(len(l), dtype=int)
		for i in range(W):
			tmp += l[:, i]
			if np.max(tmp) > K:
				cut += 1
				tmp = l[:, i]
			if cut >= ans:
				break

		ans = ans if ans <= cut else cut

	print(ans)

if __name__ == '__main__':
	main()

Buggy python submission (verdict: Time Limit Exceeded):
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, radians
from itertools import accumulate, permutations, combinations, product
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left
from fractions import gcd
from heapq import heappush, heappop
from functools import reduce
import numpy as np
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
def ZIP(n): return zip(*(MAP() for _ in range(n)))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7

H, W, K = MAP()
S = np.array([list(map(int, list(input()))) for _ in range(H)])

ans = INF
for x in product([0, 1], repeat=H-1):
	cut = sum(x)
	if cut >= ans:
			continue
	if any(x):
		lis = np.zeros((H, W+1))
		tmp_lis = np.zeros((W))
		idx = 0
		for i, n in enumerate(x):
			tmp_lis += S[i]
			if n:
				lis[idx][1:] += tmp_lis
				idx += 1
				tmp_lis = np.zeros((W))
				
		if H >= 2:
			tmp_lis += S[-1]
			lis[idx][1:] += tmp_lis
		if (lis>K).sum():
			continue
		lis = lis.cumsum(axis=1)
	else:
		lis = np.sum(S, axis=0)
		tmp = 0
		for n in lis:
			if n > K:
				cut = INF
				break
			tmp += n
			if tmp > K:
				cut += 1
				tmp = n
		ans = min(ans, cut)
		continue
	idxs = []
	idx = 0
	while idx != W:
		for i in range(len(lis)):
			for j in range(idx, W+1):
				if lis[i][j]-lis[i][idx] > K:  # 1番最初にKを超えるところを探す
					idxs.append(j)

		if not idxs:  # 超えない
			break

		idx = min(idxs)-1
		idxs = []
		cut += 1
		if cut >= ans:
			break
	ans = min(ans, cut)

print(ans)


Fixed submission:
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, radians
from itertools import accumulate, permutations, combinations, product
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left
from fractions import gcd
from heapq import heappush, heappop
from functools import reduce
import numpy as np
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
def ZIP(n): return zip(*(MAP() for _ in range(n)))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7

def main():
	H, W, K = MAP()
	S = np.array([list(map(int, list(input()))) for _ in range(H)])

	ans = INF
	for x in product([0, 1], repeat=H-1):
		cut = np.sum(x)
		if cut >= ans:
				continue
		r = 0
		l = []
		for i in range(H-1):
			if x[i]:
				l.append(np.sum(S[r:i+1, :], axis=0))
				r = i + 1
		l.append(np.sum(S[r:, :], axis=0))
		l = np.array(l)
		if np.max(l) > K:
			continue
		tmp = np.zeros(len(l), dtype=int)
		for i in range(W):
			tmp += l[:, i]
			if np.max(tmp) > K:
				cut += 1
				tmp = l[:, i]
			if cut >= ans:
				break

		ans = ans if ans <= cut else cut

	print(ans)

if __name__ == '__main__':
	main()

Buggy python submission (verdict: Time Limit Exceeded):
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, radians
from itertools import accumulate, permutations, combinations, product
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left
from fractions import gcd
from heapq import heappush, heappop
from functools import reduce
import numpy as np
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
def ZIP(n): return zip(*(MAP() for _ in range(n)))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7

H, W, K = MAP()
S = np.array([list(map(int, list(input()))) for _ in range(H)])

ans = INF
for x in product([0, 1], repeat=H-1):
	cut = sum(x)
	if any(x):
		lis = np.zeros((H, W+1))
		tmp_lis = np.zeros((W))
		idx = 0
		for i, n in enumerate(x):
			tmp_lis += S[i]
			if n:
				lis[idx][1:] += tmp_lis
				idx += 1
				tmp_lis = np.zeros((W))
				
		if H >= 2:
			tmp_lis += S[-1]
			lis[idx][1:] += tmp_lis
		if (lis>K).sum():
			continue
		lis = lis.cumsum(axis=1)
	else:
		lis = np.sum(S, axis=0)
		tmp = 0
		for n in lis:
			if n > K:
				cut = INF
				break
			tmp += n
			if tmp > K:
				cut += 1
				tmp = n
		ans = min(ans, cut)
		continue
	idxs = []
	idx = 0
	while idx != W:
		for i in range(len(lis)):
			for j in range(idx, W+1):
				if lis[i][j]-lis[i][idx] > K:  # 1番最初にKを超えるところを探す
					idxs.append(j)

		if not idxs:  # 超えない
			break

		idx = min(idxs)-1
		idxs = []
		cut += 1
	ans = min(ans, cut)

print(ans)


Fixed submission:
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, radians
from itertools import accumulate, permutations, combinations, product
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left
from fractions import gcd
from heapq import heappush, heappop
from functools import reduce
import numpy as np
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
def ZIP(n): return zip(*(MAP() for _ in range(n)))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7

def main():
	H, W, K = MAP()
	S = np.array([list(map(int, list(input()))) for _ in range(H)])

	ans = INF
	for x in product([0, 1], repeat=H-1):
		cut = np.sum(x)
		if cut >= ans:
				continue
		r = 0
		l = []
		for i in range(H-1):
			if x[i]:
				l.append(np.sum(S[r:i+1, :], axis=0))
				r = i + 1
		l.append(np.sum(S[r:, :], axis=0))
		l = np.array(l)
		if np.max(l) > K:
			continue
		tmp = np.zeros(len(l), dtype=int)
		for i in range(W):
			tmp += l[:, i]
			if np.max(tmp) > K:
				cut += 1
				tmp = l[:, i]
			if cut >= ans:
				break

		ans = ans if ans <= cut else cut

	print(ans)

if __name__ == '__main__':
	main()