[SWEA] 2105. [シミュレーションソフト機能テスト]デザートカフェ


📚 質問する


https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5VwAr6APYDFAWu&categoryId=AV5VwAr6APYDFAWu&categoryType=CODE&problemTitle=%EB%94%94%EC%A0%80%ED%8A%B8+%EC%B9%B4%ED%8E%98&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1

📖 に答える


再帰的なバックトラックを活用する.
移動する方向は4方向に移動せず、始点を基準に一定の方向に移動して矩形を描きます.

右下、左下、左上、右上の順に描くことを約束します.
直進または折出しの2つの組み合わせは、再帰を体現している.
曲がるたびに、1つ以上の方向に移動したり曲がったりします.
問題では以下のように与えられているからです.

また、2回折った後から、直線と方向転換の組み合わせにならず、四角形を描くとよいでしょう.
2辺が完成したので長方形の道を決めました.

上記の場合、カーブを曲がると、残りの道が自動的に決定されます.
以下のとおりです.

したがって,cur 2以上から条件文を用いて異なる処理を行うべきである.
私はcurを2,y,xの和と起点i,jの和とは異なり,前進を続けたり,折れたりするように設定した.Curが3の場合、始点に出合えばよいので、y座標が同じ場合に出力します.
直行が考えるポイントは同じデザートを食べないこと.
ということで、デザートを食べるたびに訪問しています.
このとき最も重要なのは、復帰終了時に必ず訪問を再開することです.
枝刈りのために矩形を実現した2辺がこれまで求めた矩形の2辺より小さい場合は確認しない.

📒 コード#コード#

def moving(d, y, x, cnt):       # 움직이기
    ny = y + dy[d]
    nx = x + dx[d]
    if 0 <= ny < n and 0 <= nx < n and visited[arr[ny][nx]] == 0:
        visited[arr[ny][nx]] = 1        # 방문 표시
        recur(d, ny, nx, cnt + 1, 1)
        visited[arr[ny][nx]] = 0        # 재귀를 빠져 나오면 방문 표시 제거


def recur(cur, y, x, cnt, move):
    global max_cnt
    if cur == 3 and i == y:             # 사각형 완성했을 때
        max_cnt = max(max_cnt, cnt)     # 최댓값 업데이트
        return
    if cur == 2 and max_cnt > cnt * 2:  # 가지치기 두 변의 길이가 현재 값보다 작으면 return
        return
    if cur == 2 and i + j == y + x:     # 두 변을 그린 후부터는 변의 길이에 맞춰 잇는다.
        recur(cur + 1, y, x, cnt, 0)    # 마지막 세번째 꺾고 시작점으로 잇는다.
        return
    # 가던 방향으로 움직인다.
    moving(cur, y, x, cnt)
    # 방향 전환 - 2번까지 임의로 꺾고 3번부터는 사각형을 그리니 임의로 꺾지 않는다.
    if cur < 2 and move:    # 한 번이라도 움직였을 때 꺾는다.
        recur(cur + 1, y, x, cnt, 0)


dy = [1, 1, -1, -1]     # 움직일 순서 : 오른쪽 아래, 왼쪽 아래, 왼쪽 위, 오른쪽 위
dx = [1, -1, -1, 1]
for tc in range(1, 1 + int(input())):
    n = int(input())
    arr = [list(map(int, input().split())) for _ in range(n)]
    visited = [0 for _ in range(101)]       # 중복 확인하기 위함
    max_cnt = 0                             # 출력할 결과

    for i in range(n):          # 모든 점에서 start
        for j in range(n):
            recur(0, i, j, 0, 0)

    if max_cnt == 0:            # 사각형을 그릴 수 없으면 -1 출력
        print(f'#{tc} -1')
    else:
        print(f'#{tc} {max_cnt}')

🔍 結果