[BOJ]14500-トロミノ
36205 ワード
質問リンク
トロミノ
問題の説明
ポリオミ黄色とは、1*1サイズの正方形が複数あるパターンを意味します.トロミノは4つの正方形からなるドオミノで、このトロミノはあります
5種類あります.1000個未満の自然数が書かれたN*Mサイズの紙ごとに、正方形を1つ置くには、1つの正方形しか含まれず、回転して対称にすることができます.テトロミノが手配したカンソ協定の最大限度は?
問題を解く
90度180度270度、x軸y軸対称などの格子を初めて回してみましたが失敗しました^^
試してみる。
特定の格子から始め,dfsを用いて可能なすべてのテトロミノブロックのリストを可能な値に入れ,可能な値リストで最大値を探した.時間が経つと、必ずしも可能性リストに保存して最大値を探すのではなく、dfsを迂回して可能なトロミノを探すときに最大値を更新することで、時間を減らすことができます.
2-dfsを試します
ポリオミ黄色とは、1*1サイズの正方形が複数あるパターンを意味します.トロミノは4つの正方形からなるドオミノで、このトロミノはあります
5種類あります.1000個未満の自然数が書かれたN*Mサイズの紙ごとに、正方形を1つ置くには、1つの正方形しか含まれず、回転して対称にすることができます.テトロミノが手配したカンソ協定の最大限度は?
問題を解く
90度180度270度、x軸y軸対称などの格子を初めて回してみましたが失敗しました^^
試してみる。
特定の格子から始め,dfsを用いて可能なすべてのテトロミノブロックのリストを可能な値に入れ,可能な値リストで最大値を探した.時間が経つと、必ずしも可能性リストに保存して最大値を探すのではなく、dfsを迂回して可能なトロミノを探すときに最大値を更新することで、時間を減らすことができます.
2-dfsを試します
#(x,y)를 시작으로 4칸 찾기
def dfs(x, y, block, count, max_num):
global answer
if count == 4:
answer = max(answer, max_num)
return
for i in range(4):
nx, ny = x+dx[i], y+dy[i]
if in_range(nx, ny) and (nx, ny) not in block:
dfs(nx, ny, block+[(nx, ny)], count+1, max_num+board[nx][ny])
-> dfs, bfs를 이용하면 다섯개의 테트로미노 종류중 'ㅗ' 모양을 갖는 테트로미노는 찾을 수 없다.
->範囲内で凸形状が可能な場合は、凸形状の格子の和を求めてmaxを更新します
->範囲内で+の形ができれば、+を形成する格子の和から東西南北の格子ごとに最小値を外します.
def exception(x, y):
global answer
tmp = []
min_val = 1000
for i in range(4):
if in_range(x+dx[i], y+dy[i]):
min_val = min(min_val, board[x+dx[i]][y+dy[i]])
tmp.append((x+dx[i], y+dy[i]))
# 범위 내에 ㅗ모양이 가능하면
if len(tmp) == 3:
tmp.append((x,y))
answer = max(answer, get_score(tmp))
#범위 내에 +모양이 가능하면 -> 네방향중 제일 작은 칸 빼서 ㅗ로 만들기
elif len(tmp) == 4:
tmp.append((x,y))
answer = max(answer, get_score(tmp)-min_val)
完全なコード
import sys
input = sys.stdin.readline
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
answer = 0
N, M = map(int, input().split())
board = []
for _ in range(N):
board.append(list(map(int, input().split())))
def in_range(x, y):
if x in range(N) and y in range(M):
return True
return False
def get_score(blocks):
total = 0
for block in blocks:
total += board[block[0]][block[1]]
return total
#(x,y)를 시작으로 4칸 찾기 -> ㅗ모양은 포함 못함 ㅠ
def dfs(x, y, block, count, max_num):
global answer
if count == 4:
answer = max(answer, max_num)
return
for i in range(4):
nx, ny = x+dx[i], y+dy[i]
if in_range(nx, ny) and (nx, ny) not in block:
dfs(nx, ny, block+[(nx, ny)], count+1, max_num+board[nx][ny])
def exception(x, y):
global answer
tmp = []
min_val = 1000
for i in range(4):
if in_range(x+dx[i], y+dy[i]):
min_val = min(min_val, board[x+dx[i]][y+dy[i]])
tmp.append((x+dx[i], y+dy[i]))
# 범위 내에 ㅗ모양이 가능하면
if len(tmp) == 3:
tmp.append((x,y))
answer = max(answer, get_score(tmp))
#범위 내에 +모양이 가능하면 -> 네방향중 제일 작은 칸 빼서 ㅗ로 만들기
elif len(tmp) == 4:
tmp.append((x,y))
answer = max(answer, get_score(tmp)-min_val)
for i in range(N):
for j in range(M):
dfs(i, j, [(i,j)], 1, board[i][j])
#+모양도 추가하기
exception(i, j)
print(answer)
試し3-bfs
bfsで解いてみると、やはりdfsの方が直感的で編成しやすいので、
import sys
from collections import deque
input = sys.stdin.readline
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
answer = 0
N, M = map(int, input().split())
board = []
for _ in range(N):
board.append(list(map(int, input().split())))
def in_range(x, y):
if x in range(N) and y in range(M):
return True
return False
def bfs(x,y):
max_num = 0
queue = deque()
#x, y, 이전 x, 이전 y, count, total_score
queue.append((x, y, 0, 0, 1, board[x][y]))
while queue:
x, y, pre_x, pre_y, cnt, total_score = queue.popleft()
if cnt == 4:
max_num = max(max_num, total_score)
continue
for i in range(4):
nx, ny = x+dx[i], y+dy[i]
#이동한 좌표가 행렬의 범위를 만족하고, 해당 이동이 이전 좌표로의 이동이 아니면 !!
if in_range(nx, ny) and (nx, ny) != (pre_x, pre_y):
queue.append((nx, ny, x, y, cnt+1, total_score+board[nx][ny]))
return max_num
def get_score(blocks):
total = 0
for block in blocks:
total += board[block[0]][block[1]]
return total
def exception(x, y):
global answer
tmp = []
min_val = 1000
for i in range(4):
if in_range(x+dx[i], y+dy[i]):
min_val = min(min_val, board[x+dx[i]][y+dy[i]])
tmp.append((x+dx[i], y+dy[i]))
# 범위 내에 ㅗ모양이 가능하면
if len(tmp) == 3:
tmp.append((x,y))
answer = max(answer, get_score(tmp))
#범위 내에 +모양이 가능하면 -> 네방향중 제일 작은 칸 빼서 ㅗ로 만들기
elif len(tmp) == 4:
tmp.append((x,y))
answer = max(answer, get_score(tmp)-min_val)
for i in range(N):
for j in range(M):
answer = max(answer, bfs(i,j))
#+모양도 추가하기
exception(i, j)
print(answer)
に感銘を与える
テトロミノを直接回転させるために、3時間も飛んだように^ㅇ^,接着剤を探して、可能性のあるテトロミノ座標をハードコーディングして見つけたコードをたくさん見つけましたが、出題者の意図はそうではないようで悩んでいましたが、dfsは凸形が見つからないので,これは別の考慮が必要であり,これは難題のようだ.
本当に大変でしたが、
Reference
この問題について([BOJ]14500-トロミノ), 我々は、より多くの情報をここで見つけました
https://velog.io/@woo0_hooo/BOJ-14500-테트로미노
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
Reference
この問題について([BOJ]14500-トロミノ), 我々は、より多くの情報をここで見つけました https://velog.io/@woo0_hooo/BOJ-14500-테트로미노テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol