Problem:


Score : 500 points

Problem Statement

We have a chocolate bar partitioned into H horizontal rows and W vertical columns of squares.

The square (i, j) at the i-th row from the top and the j-th column from the left is dark if S_{i,j} is 0, and white if S_{i,j} is 1.

We will cut the bar some number of times to divide it into some number of blocks. In each cut, we cut the whole bar by a line running along some boundaries of squares from end to end of the bar.

How many times do we need to cut the bar so that every block after the cuts has K or less white squares?

Constraints

1 \leq H \leq 10

1 \leq W \leq 1000

1 \leq K \leq H \times W

S_{i,j} is 0 or 1.

Input

Input is given from Standard Input in the following format:

H W K
S_{1,1}S_{1,2}...S_{1,W}
:
S_{H,1}S_{H,2}...S_{H,W}

Output

Print the number of minimum times the bar needs to be cut so that every block after the cuts has K or less white squares.

Sample Input 1

3 5 4
11100
10001
00111

Sample Output 1

2

For example, cutting between the 1-st and 2-nd rows and between the 3-rd and 4-th columns - as shown in the figure to the left - works.

Note that we cannot cut the bar in the ways shown in the two figures to the right.

Sample Input 2

3 5 8
11100
10001
00111

Sample Output 2

0

No cut is needed.

Sample Input 3

4 10 4
1110010010
1000101110
0011101001
1101000111

Sample Output 3

3



Sample input:
3 5 4
11100
10001
00111


Sample output:
2

Submission status: Wrong Answer

Solution code:
import bisect, collections, copy, heapq, itertools, math, string
import sys
def I(): return int(sys.stdin.readline().rstrip())
def MI(): return map(int, sys.stdin.readline().rstrip().split())
def LI(): return list(map(int, sys.stdin.readline().rstrip().split()))
def S(): return sys.stdin.readline().rstrip()
def LS(): return list(sys.stdin.readline().rstrip().split())

from collections import deque
H, W, K = MI()
S_ = [[] for _ in range(W)]
for i in range(H):
    s = S()
    for j in range(len(s)):
        S_[j].append(int(s[j]))



A = []
for i in range(2 ** (H - 1)):
    A_bit = []
    for j in range(H - 1):
        # 二進数表記でj回右にシフトして0桁目（一番下の桁）が1であればTrue
        if ((i >> j) & 1):
            A_bit.append(j)
    A.append(A_bit)


Ans_list = []
for a in A:
    sums = [0] * (len(a) + 1)
    ele = [0] * (len(a) + 1)
    ans = 0
    for s_ in S_:
        queue = deque(a)
        if queue == deque([]):
            ele[0] = sum(s_)
            if ele[0] > K:
                ans = 10 ** 6
                break
            sums[0] += sum(s_)
        else:
            x = queue.popleft()
            ele[0] = sum(s_[0:x + 1])
            if ele[0] > K:
                ans = 10 ** 6
                break
            sums[0] += sum(s_[0:x + 1])
            j = 1
            while queue != deque([]):
                y = queue.popleft()
                ele[j] = sum(s_[x + 1:y + 1])
                if ele[j] > K:
                    ans = 10 ** 6
                    break
                sums[j] += sum(s_[x + 1:y + 1])
                x = y
                j += 1
            ele[len(a)] = sum(s_[x + 1:H])
            sums[len(a)] += sum(s_[x + 1:H])
        if max(sums) > K:
            ans += 1
            for k in range(len(a) + 1):
                sums[k] = ele[k]
    ans += len(a)
    Ans_list.append(ans)

print(min(Ans_list))

Submission status: Wrong Answer

Solution code:
import bisect, collections, copy, heapq, itertools, math, string
import sys
def I(): return int(sys.stdin.readline().rstrip())
def MI(): return map(int, sys.stdin.readline().rstrip().split())
def LI(): return list(map(int, sys.stdin.readline().rstrip().split()))
def S(): return sys.stdin.readline().rstrip()
def LS(): return list(sys.stdin.readline().rstrip().split())

from collections import deque
H, W, K = MI()
S_ = [[] for _ in range(W)]
for i in range(H):
    s = S()
    for j in range(len(s)):
        S_[j].append(int(s[j]))



A = []
for i in range(2 ** (H - 1)):
    A_bit = []
    for j in range(H - 1):
        # 二進数表記でj回右にシフトして0桁目（一番下の桁）が1であればTrue
        if ((i >> j) & 1):
            A_bit.append(j)
    A.append(A_bit)


Ans_list = []
for a in A:
    sums = [0] * (len(a) + 1)
    ele = [0] * (len(a) + 1)
    ans = 0
    for s_ in S_:
        queue = deque(a)
        if queue == deque([]):
            ele[0] = sum(s_)
            sums[0] += sum(s_)
        else:
            x = queue.popleft()
            ele[0] = sum(s_[0:x + 1])
            sums[0] += sum(s_[0:x + 1])
            j = 1
            while queue != deque([]):
                y = queue.popleft()
                ele[j] = sum(s_[x + 1:y + 1])
                sums[j] += sum(s_[x + 1:y + 1])
                x = y
                j += 1
            ele[len(a)] = sum(s_[x + 1:H])
            sums[len(a)] += sum(s_[x + 1:H])
        if max(sums) > K:
            ans += 1
            for k in range(len(a) + 1):
                sums[k] = ele[k]
    ans += len(a)
    Ans_list.append(ans)

print(min(Ans_list))

Submission status: Wrong Answer

Solution code:
h,w,k = map(int,input().split())
s = [list(map(int, input())) for i in range(h)]
ans = h+w-2
for i in range(2**(h-1)):
    index = [0] * h
    rowcuts = 0
    for j in range(h-1):
        if 1 & (i >> j) == 1:
            rowcuts += 1
        index[j + 1] = rowcuts
    chocos = [0] * (rowcuts + 1)
    coulmncuts = 0
    for j in range(w):
        for l in range(h):
            chocos[index[l]] += s[l][j]
        if max(chocos) > k:
            coulmncuts += 1
            chocos = [0] * (rowcuts + 1)
            for l in range(h):
                chocos[index[l]] += s[l][j]
    ans = min(ans, rowcuts + coulmncuts)
print(ans)

Submission status: Wrong Answer

Solution code:
H,W,K=map(int,input().split())
s=[[int(x) for x in list(input())] for _ in range(H)]
ans = H*W
for h in range(2**(H-1)):
  parts = list()
  upper = 0
  cnt = 0
  for j in range(H-1):
    if h >> j & 1:
      cnt += 1
      parts.append([sum([s[y][x] for y in range(upper, j+1)]) for x in range(W)])
      upper = j+1
  parts.append([sum([s[y][x] for y in range(upper, H)]) for x in range(W)])
  # 貪欲
  summary = [0]*len(parts)
  for i in range(W):
    temp_sum = [summary[j] + parts[j][i] for j in range(len(parts))]
    for ts in temp_sum:
      if ts > K:
        cnt += 1
        summary = [parts[j][i] for j in range(len(parts))]
        break
    else:
      summary = temp_sum
  ans = min(ans, cnt)
print(ans)

Submission status: Wrong Answer

Solution code:
from itertools import product


def makelist(BIT):
    LIST, tmp = [], s[0]
    for i, bi in enumerate(BIT, 1):
        if bi == 1:
            LIST.append(tmp)
            tmp = s[i]
        elif bi == 0:
            tmp = [p + q for p, q in zip(tmp, s[i])]
    else:
        LIST.append(tmp)
    return LIST


def solve(LIST):
    CNT, tmp = 0, [l[0] for l in LIST]
    if any(num > k for num in tmp):
        return h * w
    for i in range(1, w):
        cal = [tmp[j] + LIST[j][i] for j in range(len(LIST))]
        if any(num > k for num in cal):
            CNT += 1
            tmp = [l[i] for l in LIST]
        else:
            tmp = cal
    return CNT


h, w, k = map(int, input().split())
s = [[int(sij) for sij in input()] for _ in range(h)]

ans = h * w
for bit in product([0, 1], repeat=(h - 1)):
    numlist = makelist(bit)
    ans = min(ans, solve(numlist) + sum(bit))
    print(solve(numlist) + sum(bit))
print(ans)

Submission status: Wrong Answer

Solution code:
from itertools import product


def makelist(BIT):
    LIST, tmp = [], s[0]
    for i, bi in enumerate(BIT, 1):
        if bi == 1:
            LIST.append(tmp)
            tmp = s[i]
        elif bi == 0:
            tmp = [p + q for p, q in zip(tmp, s[i])]
    else:
        LIST.append(tmp)
    return LIST


def solve(LIST):
    CNT, tmp = 0, [l[0] for l in LIST]
    for i in range(1, w):
        cal = [tmp[j] + LIST[j][i] for j in range(len(LIST))]
        if any(num > k for num in cal):
            CNT += 1
            tmp = [l[i] for l in LIST]
        else:
            tmp = cal
    return CNT


h, w, k = map(int, input().split())
s = [[int(sij) for sij in input()] for _ in range(h)]

ans = h * w
for bit in product([0, 1], repeat=(h - 1)):
    numlist = makelist(bit)
    ans = min(ans, solve(numlist) + sum(bit))
print(ans)

Submission status: Wrong Answer

Solution code:
import sys
from io import StringIO
import unittest
import os

# 再帰処理上限(dfs作成時に設定するのが面倒なので限度近い値を組み込む)
sys.setrecursionlimit(999999999)


# 実装を行う関数
def resolve(test_def_name=""):
    h, w, k = map(int, input().split())
    s_s = [list(input()) for i in range(h)]

    # パターン数分の情報を作成(横に切る = 最大2^10個)
    # 全パターンの・・横に切る回数、と切る場所
    side = []
    for i in range(1 << h - 1):
        cut_cnt = 0
        point_s = []
        # パターンの桁数分ループ
        for j in range(h - 1):
            # フラグが立つ(bitが1)の場合の処理を以下に記載。
            if i & 1 << j:
                cut_cnt += 1
                point_s.append(j + 1)

        point_s.append(h)
        # 得た情報をリストに追加
        side.append([point_s, cut_cnt])

    ## 横切り必須にもかかわらず、横木入りしていないパターンを排除できていない・・と思われる。
    x_s_s = list(zip(*s_s))
    ans = 999999
    for side_cut_point_s, cut_cnt in side:
        # 横切りを実施した後の塊を取得
        cnt_s = [0 for i in range(cut_cnt + 1)]

        for x_s in x_s_s:
            start = 0
            for cnt, side_cut_point in enumerate(side_cut_point_s):
                cnt_s[cnt] += x_s[start: side_cut_point].count("1")
                start += side_cut_point
            # 切る必要がある場合は切る
            if max(cnt_s) > k:
                cut_cnt += 1
                start = 0
                for cnt, side_cut_point in enumerate(side_cut_point_s):
                    cnt_s[cnt] = x_s[start: side_cut_point].count("1")
                    start += side_cut_point
            if max(cnt_s) > k:
                cut_cnt += 99999
        ans = min(ans, cut_cnt)

    print(ans)


# テストクラス
class TestClass(unittest.TestCase):
    def assertIO(self, assert_input, output):
        stdout, sat_in = sys.stdout, sys.stdin
        sys.stdout, sys.stdin = StringIO(), StringIO(assert_input)
        resolve(sys._getframe().f_back.f_code.co_name)
        sys.stdout.seek(0)
        out = sys.stdout.read()[:-1]
        sys.stdout, sys.stdin = stdout, sat_in
        self.assertEqual(out, output)

    def test_input_1(self):
        test_input = """3 5 4
11100
10001
00111"""
        output = """2"""
        self.assertIO(test_input, output)

    def test_input_2(self):
        test_input = """3 5 8
11100
10001
00111"""
        output = """0"""
        self.assertIO(test_input, output)

    def test_input_3(self):
        test_input = """4 10 4
1110010010
1000101110
0011101001
1101000111"""
        output = """3"""
        self.assertIO(test_input, output)

    # 自作テストパターンのひな形(利用時は「tes_t」のアンダーバーを削除すること
    def test_1original_1(self):
        test_input = """3 5 1
11110
10011
00111"""
        output = """6"""

        self.assertIO(test_input, output)


# 実装orテストの呼び出し
if __name__ == "__main__":
    if os.environ.get("USERNAME") is None:
        # AtCoder提出時の場合
        resolve()

    else:
        # 自PCの場合
        unittest.main()

Submission status: Wrong Answer

Solution code:
h,w,kk=list(map(int,input().split()))
s=[list(map(int,list(input()))) for i in range(h)]
l=[]
for i in range(2**(h-1)):
  ll=[0]
  for j in range(h-1):
    if i & 2**j:
      ll.append(ll[-1]+1)
    else:
      ll.append(ll[-1])
  l.append(ll)

mc=w+h
for i in l:
  c=[0 for i in range(h)]
  cc=0
  f=1
  #print(i,0)
  for j in range(w):
    #print(c)
    ff=0
    for k in range(h):
      c[i[k]]+=s[k][j]
    for k in range(h):
      if c[k]>kk:
        ff=1
        break
    if ff:
      if f:
        cc=w+h
        print(c)
        break
      cc+=1
      c=[0 for i in range(h)]
      for k in range(h):
        c[i[k]]+=s[k][j]
    f=0
  #print(cc)
  if mc>cc+len(set(i))-1:
    mc=cc+len(set(i))-1
print(mc)

Submission status: Wrong Answer

Solution code:
h,w,kk=list(map(int,input().split()))
s=[list(map(int,list(input()))) for i in range(h)]
l=[]
for i in range(2**(h-1)):
  ll=[0]
  for j in range(h-1):
    if i & 2**j:
      ll.append(ll[-1]+1)
    else:
      ll.append(ll[-1])
  l.append(ll)

mc=w+h
for i in l:
  c=[0 for i in range(h)]
  cc=0
  f=1
  #print(i,0)
  for j in range(w):
    #print(c)
    ff=0
    for k in range(h):
      c[i[k]]+=s[k][j]
    for k in range(h):
      if c[k]>kk:
        ff=1
        break
    if ff:
      if f:
        cc=w+h
        print(c)
        break
      cc+=1
      c=[0 for i in range(h)]
      for k in range(h):
        c[i[k]]+=s[k][j]
    f=0
  #print(cc)
  if mc>cc+len(set(i))-1:
    mc=cc
print(mc)

Submission status: Wrong Answer

Solution code:
h,w,kk=list(map(int,input().split()))
s=[list(map(int,list(input()))) for i in range(h)]
l=[]
for i in range(2**(h-1)):
  ll=[0]
  for j in range(h-1):
    if i & 2**j:
      ll.append(ll[-1]+1)
    else:
      ll.append(ll[-1])
  l.append(ll)

mc=w+h
for i in l:
  c=[0 for i in range(h)]
  cc=0
  f=1
  #print(i,0)
  for j in range(w):
    #print(c)
    ff=0
    for k in range(h):
      c[i[k]]+=s[k][j]
    for k in range(h):
      if c[k]>kk:
        ff=1
        break
    if ff:
      if f:
        cc=w+h
        print(c)
        break
      cc+=1
      c=[0 for i in range(h)]
      for k in range(h):
        c[i[k]]+=s[k][j]
    f=0
  #print(cc)
  if mc>cc+len(set(i)):
    mc=cc
print(mc)

Submission status: Wrong Answer

Solution code:
import sys
from io import StringIO
import unittest
import os

# 再帰処理上限(dfs作成時に設定するのが面倒なので限度近い値を組み込む)
sys.setrecursionlimit(999999999)


# 実装を行う関数
def resolve(test_def_name=""):
    h, w, k = map(int, input().split())
    s_s = [list(input()) for i in range(h)]

    # パターン数分の情報を作成(横に切る = 最大2^10個)
    # 全パターンの・・横に切る回数、と切る場所
    side = []
    for i in range(1 << h - 1):
        cut_cnt = 0
        point_s = []
        # パターンの桁数分ループ
        for j in range(h - 1):
            # フラグが立つ(bitが1)の場合の処理を以下に記載。
            if i & 1 << j:
                cut_cnt += 1
                point_s.append(j + 1)

        point_s.append(h)
        # 得た情報をリストに追加
        side.append([point_s, cut_cnt])

    x_s_s = list(zip(*s_s))
    ans = 999999
    for side_cut_point_s, cut_cnt in side:
        # 横切りを実施した後の塊を取得
        cnt_s = [0 for i in range(cut_cnt + 1)]

        for x_s in x_s_s:
            start = 0
            for cnt, side_cut_point in enumerate(side_cut_point_s):
                cnt_s[cnt] += x_s[start: side_cut_point].count("1")
                start += side_cut_point
            # 切る必要がある場合は切る
            if max(cnt_s) > k:
                cut_cnt += 1
                start = 0
                for cnt, side_cut_point in enumerate(side_cut_point_s):
                    cnt_s[cnt] = x_s[start: side_cut_point].count("1")
                    start += side_cut_point
        ans = min(ans, cut_cnt)

    print(ans)


# テストクラス
class TestClass(unittest.TestCase):
    def assertIO(self, assert_input, output):
        stdout, sat_in = sys.stdout, sys.stdin
        sys.stdout, sys.stdin = StringIO(), StringIO(assert_input)
        resolve(sys._getframe().f_back.f_code.co_name)
        sys.stdout.seek(0)
        out = sys.stdout.read()[:-1]
        sys.stdout, sys.stdin = stdout, sat_in
        self.assertEqual(out, output)

    def test_input_1(self):
        test_input = """3 5 4
11100
10001
00111"""
        output = """2"""
        self.assertIO(test_input, output)

    def test_input_2(self):
        test_input = """3 5 8
11100
10001
00111"""
        output = """0"""
        self.assertIO(test_input, output)

    def test_input_3(self):
        test_input = """4 10 4
1110010010
1000101110
0011101001
1101000111"""
        output = """3"""
        self.assertIO(test_input, output)

    # 自作テストパターンのひな形(利用時は「tes_t」のアンダーバーを削除すること
    def tes_t_1original_1(self):
        test_input = """データ"""
        output = """データ"""
        self.assertIO(test_input, output)


# 実装orテストの呼び出し
if __name__ == "__main__":
    if os.environ.get("USERNAME") is None:
        # AtCoder提出時の場合
        resolve()

    else:
        # 自PCの場合
        unittest.main()

Submission status: Wrong Answer

Solution code:

def main():
    H,W,K=map(int,input().split())

    S=[]
    for i in range(H):
        col=list(map(int,list(input())))
        S.append(col)
    CumulativeS=[[S[i][0]] for i in range(H)]
    for i in range(len(S)):
        for j in range(1,len(S[i])):
            CumulativeS[i].append(CumulativeS[i][j-1]+S[i][j])
    for i in range(1,len(S)):
        for j in range(len(S[i])):
            CumulativeS[i][j]+=CumulativeS[i-1][j]
    all_bit=1<<H-1
    res=10000
    for bit in range(all_bit):
        wide_bound=[]
        for i in range(H-1):
            if (bit & (1<<i))!=0:
                wide_bound.append(i)
        res_=len(wide_bound)
        high_bound=[]
        high_flag=0
        for i in range(W):
            if len(high_bound)==0:
                for b in range(len(wide_bound)):
                    if b==0:
                        white_chocolate=CumulativeS[wide_bound[b]][i]
                    else:
                        white_chocolate=CumulativeS[wide_bound[b]][i]-CumulativeS[wide_bound[b-1]][i]

                    if white_chocolate>K:
                        if i-1<0:
                            high_flag=1
                            break
                        high_bound.append(i-1)
                        break
                    if b==len(wide_bound)-1:
                        white_chocolate=CumulativeS[H-1][i]-CumulativeS[wide_bound[b]][i]
                        if white_chocolate > K:
                            if i-1<0:
                                high_flag=1
                                break
                            high_bound.append(i - 1)


                if high_flag==1:
                    break

                if len(wide_bound)==0:
                    white_chocolate = CumulativeS[H - 1][i]
                    if white_chocolate>K:
                        if i-1<0:
                            break
                        high_bound.append(i-1)

            else:
                for b in range(len(wide_bound)):
                    if b == 0:
                        white_chocolate = CumulativeS[wide_bound[b]][i]-CumulativeS[wide_bound[b]][high_bound[len(high_bound)-1]]
                    else:
                        white_chocolate = CumulativeS[wide_bound[b]][i] - CumulativeS[wide_bound[b - 1]][i]-CumulativeS[wide_bound[b]][high_bound[len(high_bound)-1]]+CumulativeS[wide_bound[b-1]][high_bound[len(high_bound)-1]]
                    if white_chocolate>K:
                        if i-1<0:
                            high_flag=1
                            break
                        high_bound.append(i-1)
                        break
                    if b == len(wide_bound) - 1:
                        white_chocolate = CumulativeS[H - 1][i] - CumulativeS[wide_bound[b]][i]-CumulativeS[H-1][high_bound[len(high_bound)-1]]+CumulativeS[wide_bound[b]][high_bound[len(high_bound)-1]]
                        if white_chocolate>K:
                            if i-1<0:
                                high_flag=1
                                break
                            high_bound.append(i-1)

                if high_flag==1:
                    break

                if len(wide_bound)==0:
                    white_chocolate = CumulativeS[H - 1][W - 1]-CumulativeS[H-1][high_bound[len(high_bound)-1]]
                    if white_chocolate>K:
                        if i-1<0:
                            break

                        high_bound.append(i-1)
        res_+=len(high_bound)
        if res_<res:
            res=res_

    print(res)

if __name__=="__main__":
    main()

Submission status: Wrong Answer

Solution code:
h, w, k = list(map(int, input().split()))

choco = [list(map(int, list(input()))) for i in range(h)]

choco_cumsum = [[0 for i in range(w)] for j in range(h)]

for i in range(h):
    choco_cumsum[i][0] = choco[i][0]
    for j in range(1, w):
        choco_cumsum[i][j] = choco_cumsum[i][j-1] + choco[i][j]

ans = h + w + 1

for h_cut in range(2**(h-1)):
    # 上位ビットが上側。1が切る、0が切らない
    num_cut_init = bin(h_cut).count("1") # 立っているビットの個数
    num_cut = num_cut_init
    w_last_cot_pos = -1
    valid = True

    temp_list = [0] * (num_cut_init + 1)
    temp_dict = {}
    idx = 0
    temp_dict[0] = idx
    for i in range(1, h):
        # print('idx', 2 ** (-i+h-1) )
        if h_cut & (2 ** (-i+h-1) ):
            idx += 1
        # idx += h_cut & (2 ** (h-1) - i)
        temp_dict[i] = idx
    # print(temp_dict)

    iw = 0
    while iw < w:

        for ih in range(h):
            temp_list[temp_dict[ih]] += choco[ih][iw]
        # print(iw, temp_list)

        condition = max(temp_list) > k
        if condition:
            if w_last_cot_pos < iw-1:
                # もしそこで切ってkを超えるなら、その手前で切る
                num_cut += 1
                w_last_cot_pos = iw
                temp_list = [0] * (num_cut_init + 1)
                # print('iw: ', iw, 'last: ', w_last_cot_pos)

            else:
                # 1つしか動かしてないのに、Kマスを超えてしまった場合は、この横の切り方では達成不可能なので次のh_cutに
                valid = False
                break
        
        else:
            iw += 1
    
    if valid:
        ans = min(ans, num_cut)
    # print(num_cut)

print(ans)

Submission status: Wrong Answer

Solution code:
from collections import deque

H, W, K = map(int, input().split())

mp = [input() for _ in range(H)]

rlt = 1010

h = deque([[1]])

while h:
  t = h.pop()
  if len(t) == H:
    t.append(1)
    tmp = sum(t) - 2
    bs = tmp
    lst = [0]*H
    j = -1
    for i in range(len(t)-1):
      if t[i] == 1:
        j += 1
      lst[i] = j 
    cnt = [0]*(lst[-1]+1)
    for j in range(W):
      tcnt = [0]*(lst[-1]+1)
      f = 0
      for i in range(H):
        tcnt[lst[i]] += int(mp[i][j])
      for k in range(lst[-1]+1):
        if tcnt[k] > K:
          f = 2
          break
        cnt[k] += tcnt[k]
        if cnt[k] > K:
          f = 1
          break
      if f == 2:
        break
      if f == 1:
        tmp += 1
        for k in range(lst[-1]+1):
          cnt[k] = tcnt[k]
    rlt = min(rlt, tmp)
    
  else:
    for i in range(2):
      h.append(t+[i])

print(rlt)

Submission status: Wrong Answer

Solution code:
from itertools import product
h, w, k = map(int, input().split())
s = list()
best_so_far = float('inf')
for _ in range(h):
  line = input()
  s.append(list(map(int, list(line))))
# loop over possible horizontal lines, 2**9=512 possibilities
horizontal_line_choices = product([False, True], repeat=h-1)
for chosen_indices in horizontal_line_choices:
  hyperrow_values = [s[0].copy()]
  for i in range(h-1):
    if chosen_indices[i]:
      hyperrow_values.append(s[i+1])
    else:
      for dw in range(w):
        hyperrow_values[-1][dw] += s[i+1][dw]
  if any(value>k for row in hyperrow_values for value in row):
    continue
  # now got hyperrow_values, do a greedy search on vertical lines
  num_hyperrows = len(hyperrow_values)
  count_cuts = sum(chosen_indices)
  hyperrow_cumulative = [hyperrow_values[r][0] for r in range(num_hyperrows)]
  for j in range(1, w):
    if all(hyperrow_cumulative[r]+hyperrow_values[r][j]<=k for r in range(num_hyperrows)):
      for r in range(num_hyperrows):
        hyperrow_cumulative[r] += hyperrow_values[r][j]
    else:
      count_cuts += 1
      for r in range(num_hyperrows):
        hyperrow_cumulative[r] = hyperrow_values[r][j]
  best_so_far = min(best_so_far, count_cuts)
print(best_so_far)

Submission status: Wrong Answer

Solution code:
from itertools import product
h, w, k = map(int, input().split())
s = list()
best_so_far = float('inf')
for _ in range(h):
  line = input()
  s.append(list(map(int, list(line))))
# loop over possible horizontal lines, 2**9=512 possibilities
horizontal_line_choices = product([False, True], repeat=h-1)
for chosen_indices in horizontal_line_choices:
  hyperrow_values = [s[0].copy()]
  for i in range(h-1):
    if chosen_indices[i]:
      hyperrow_values.append(s[i+1])
    else:
      for dw in range(w):
        hyperrow_values[-1][dw] += s[i+1][dw]
  # now got hyperrow_values, do a greedy search on vertical lines
  num_hyperrows = len(hyperrow_values)
  count_cuts = sum(chosen_indices)
  hyperrow_cumulative = [hyperrow_values[r][0] for r in range(num_hyperrows)]
  for j in range(1, w):
    if all(hyperrow_cumulative[r]+hyperrow_values[r][j]<=k for r in range(num_hyperrows)):
      for r in range(num_hyperrows):
        hyperrow_cumulative[r] += hyperrow_values[r][j]
    else:
      count_cuts += 1
      for r in range(num_hyperrows):
        hyperrow_cumulative[r] = hyperrow_values[r][j]
  best_so_far = min(best_so_far, count_cuts)
print(best_so_far)

Submission status: Wrong Answer

Solution code:
from itertools import product
import copy
H,W,K = list(map(int, input().split()))
A = []
for i in range(H):
  A.append(list(map(int, input())))

#SM = [np.cumsum(A[i]) for i in range(H)]

ANS = []
for pat in product(['0','1'], repeat = H-1):
  res = []
  cnt = 0
  now = copy.copy(A[0])
  for i in range(1,H):
    p = pat[i-1]
    if p == '1':
      res.append(now)
      now = copy.copy(A[i])
      cnt += 1
    else:
      for j in range(W):
        now[j] += A[i][j]
  res.append(now)
  
  #print("---")
  #print(pat)
  #print(res)
  #print(cnt)
  TATE = []
  for j in range(len(res)):
    cnt2 = 0
    wk = 0
    for x in range(W):
      if wk + res[j][x] > K:
        cnt2 += 1
        wk = 0
      wk += res[j][x]

    TATE.append(cnt + cnt2)
  #print(TATE)
  ANS.append(max(TATE))
  
print(min(ANS))

Submission status: Wrong Answer

Solution code:
h,w,k=map(int,input().split())
s=[[int(j) for j in input()] for i in range(h)]
def popcount(x):
    global h
    ret=0
    for i in range(h-1):
        ret+=(x>>i&1)
    return ret
ans=1000000000000000
for i in range(2**(h-1)):
    p=popcount(i)
    div=[0]*(p+1)
    ans_sub=p
    for j in range(w):
        now=0
        div[now]+=s[0][j]
        for l in range(h-1):
            if i>>l&1:
                now+=1
            div[now]+=s[l+1][j]
        if all(i<=k for i in div):
            continue
        else:
            div=[0]*(p+1)
            now=0
            div[now]=s[0][j]
            for l in range(h-1):
                if i>>l&1:
                    now+=1
                div[now]+=s[l+1][j]
            ans_sub+=1
    ans=min(ans,ans_sub)
print(ans)

Submission status: Wrong Answer

Solution code:
# -*- coding: utf-8 -*-
import sys 
import numpy as np
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
H, W, K = map(int, readline().split())
S = [readline().decode().rstrip() for _ in range(H)]
INF = 10**30
data = [[0]*W for _ in range(H)]
for i in range(H):
    cnt = 0 
    for j in range(W):
        if S[i][j] == '1':
            cnt +=1
        data[i][j] = cnt
data = np.array(data)

ans_cnt = INF   
for bit_H in range(1 << (H-1)):
    cnt = 0
    ans = []
    new_data = []
    for i in range(H-1):
        if (bit_H >> i) & 1:
            ans.append(i)
    ans.append(H-1)
    tmp = [0]*W
    for i in range(H):
        tmp += data[i]
        if i in ans:
            new_data.append(tmp)
            tmp = [0]*W
    new_data = np.array(new_data)
    l = len(new_data)
    cnt += l-1
    for i in range(W):
        max_cnt = 0
        for j in range(l):
            max_cnt = max(new_data[j][i],max_cnt)
        if max_cnt > K and i >=1:
            cnt +=1
            for k in range(l):
                new_data[k] -= new_data[k][i-1]
        for j in range(l):
            max_cnt = max(new_data[j][i],max_cnt)
        if max_cnt > K:
            cnt = INF
            break 
    ans_cnt = min(ans_cnt,cnt)
print(ans_cnt)

Submission status: Wrong Answer

Solution code:
import sys
import math
from collections import deque

sys.setrecursionlimit(1000000)
MOD = 10 ** 9 + 7
input = lambda: sys.stdin.readline().strip()
NI = lambda: int(input())
NMI = lambda: map(int, input().split())
NLI = lambda: list(NMI())
SI = lambda: input()


def make_grid(h, w, num): return [[int(num)] * w for _ in range(h)]


def main():
    H, W, K = NMI()
    choco = [SI() for _ in range(H)]
    ans = 100000
    for case in range(2**(H-1)):
        groups = [[0]]
        for i in range(H-1):
            if (case >> i) & 1:
                groups[-1].append(i+1)
            else:
                groups.append([i+1])
        white = [0] * len(groups)

        is_cont = False
        is_badcase = False
        cut = len(groups) - 1
        for w in range(W):
            diff = [0] * len(groups)
            for gi, group in enumerate(groups):
                for h in group:
                    if choco[h][w] == "1":
                        white[gi] += 1
                        diff[gi] += 1
            if max(white) <= K:
                is_cont = True
                continue

            if max(diff) > K:
                is_badcase = True
                break

            if is_cont:
                cut += 1
                white = diff[:]
                is_cont = False
                continue

        if not is_badcase:
            ans = min(ans, cut)

    print(ans)



if __name__ == "__main__":
    main()

Submission status: Wrong Answer

Solution code:
import sys
import math
from collections import deque

sys.setrecursionlimit(1000000)
MOD = 10 ** 9 + 7
input = lambda: sys.stdin.readline().strip()
NI = lambda: int(input())
NMI = lambda: map(int, input().split())
NLI = lambda: list(NMI())
SI = lambda: input()


def make_grid(h, w, num): return [[int(num)] * w for _ in range(h)]


def main():
    H, W, K = NMI()
    choco = [SI() for _ in range(H)]
    ans = 100000
    for case in range(2**(H-1)):
        groups = [[0]]
        for i in range(H-1):
            if (case >> i) & 1:
                groups[-1].append(i+1)
            else:
                groups.append([i+1])
        white = [0] * len(groups)

        is_cont = False
        is_badcase = False
        cut = len(groups) - 1
        for w in range(W):
            diff = [0] * len(groups)
            for gi, group in enumerate(groups):
                for h in group:
                    if choco[h][w] == "1":
                        white[gi] += 1
                        diff[gi] += 1
            if max(white) <= K:
                is_cont = True
                continue

            elif is_cont:
                cut += 1
                white = diff.copy()
                is_cont = False
                continue

            else:
                is_badcase = True
                break

        if not is_badcase:
            ans = min(ans, cut)

    print(ans)



if __name__ == "__main__":
    main()