saleo note

感想文

[python] ABC196 D Hanjo

1.方針

まず、並べて実験してみる。

すると、長方形の畳をA枚並べると、正方形の畳の敷き方は一通りに定まることがわかる。

長方形の畳の並べ方は、左上の1メートル四方のスペースから順に敷き詰めていくと考えると、各スペース毎に「横向きに敷く」「縦向きに敷く」「何も敷かない」の3通りある

計算量は3**16だが、再帰が途中で打ち切られるパターンもあるので、間に合いそう。

2.ソースコード
コードの途中でresを初期化しておかないと、resの値が累積的に計算されるので注意。
イメージとしては、再帰の底の値だけを拾ってくるイメージ。

h, w, a, b = map(int, input().split())

used = [[False]*(w) for _ in range(h)]
# print(used)
def recursion(x, y, a):
  if a == 0:
    return 1
  
  if y == h:
    return 0
  
  if x == w:
    return recursion(0, y+1, a)
  
  if used[y][x]:
    return recursion(x+1, y, a)

  res = 0

  # 横向きに敷く
  if x + 1 <= w - 1:
    if not used[y][x+1]:
      used[y][x] = used[y][x+1] = True
      res += recursion(x+2, y, a-1)
      used[y][x] = used[y][x+1] = False
  
  # 縦向きに敷く
  if y + 1 <= h - 1:
    if not used[y+1][x]:
      used[y][x] = used[y+1][x] = True
      res += recursion(x+1, y, a-1)
      used[y][x] = used[y+1][x] = False
  
  # 何も敷かん
  res += recursion(x+1, y, a)

  return res

ans = recursion(0, 0, a)

print(ans)

※resをグローバル関数として、if a== 0:のときに+1する処理でもok
https://atcoder.jp/contests/abc196/submissions/28797922