coding test

[파이썬, Java] 1987. 알파벳

잔망루피 2021. 10. 7. 18:16

문제

세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다.

말은 상하좌우로 인접한 네 칸 중의 한 칸으로 이동할 수 있는데, 새로 이동한 칸에 적혀 있는 알파벳은 지금까지 지나온 모든 칸에 적혀 있는 알파벳과는 달라야 한다. 즉, 같은 알파벳이 적힌 칸을 두 번 지날 수 없다.

좌측 상단에서 시작해서, 말이 최대한 몇 칸을 지날 수 있는지를 구하는 프로그램을 작성하시오. 말이 지나는 칸은 좌측 상단의 칸도 포함된다.

입력

첫째 줄에 R과 C가 빈칸을 사이에 두고 주어진다. (1 ≤ R,C ≤ 20) 둘째 줄부터 R개의 줄에 걸쳐서 보드에 적혀 있는 C개의 대문자 알파벳들이 빈칸 없이 주어진다.

출력

첫째 줄에 말이 지날 수 있는 최대의 칸 수를 출력한다.

예제 입력 1 

2 4

CAAB

ADCB

예제 출력 1 

3

예제 입력 2 

3 6

HFDFFB

AJHGDH

DGAGEH

예제 출력 2 

6

예제 입력 3 

5 5

IEFCJ

FHFKC

FFALF

HFGCF

HMCHH

예제 출력 3 

10

 

 

🎀 나의 풀이

# Pypy3로 제출시 통과
import sys
input=sys.stdin.readline

R, C=map(int, input().split())      # 세로, 가로
board=[input() for _ in range(R)]
length=1
ans=0
visit=[0]*26
dx=[0, 0, -1, 1]
dy=[1, -1, 0, 0]

def dfs(x, y, length) :
    global ans
    ans=max(length, ans)

    for d in range(4) :
        nx=dx[d]+x
        ny=dy[d]+y
        if 0 <= nx < R and 0 <= ny < C :
            if not visit[ord(board[nx][ny])-ord('A')] :
                visit[ord(board[nx][ny])-ord('A')]=1
                dfs(nx, ny, length+1)
                visit[ord(board[nx][ny])-ord('A')]=0

    return ans

visit[ord(board[0][0])-ord('A')]=1
print(dfs(0, 0, length))

pypy3로 제출해야 통과

다른 언어들은 백트래킹으로 구현하면 통과되던데...

왜 파이썬으로 백트래킹 구현하니까 시간초과야???

파이썬이 느리긴 하구나,,

 

 

# 시간초과
import sys
input=sys.stdin.readline

R, C=map(int, input().split())      # 세로, 가로
board=[input() for _ in range(R)]
length=1
ans=0
visit=set(board[0][0])
dx=[0, 0, -1, 1]
dy=[1, -1, 0, 0]

def dfs(x, y) :
    global length, ans
    ans=max(length, ans)

    for d in range(4) :
        nx=dx[d]+x
        ny=dy[d]+y
        if 0 <= nx < R and 0 <= ny < C :
            if board[nx][ny] not in visit :
                visit.add(board[nx][ny])
                length+=1
                dfs(nx, ny)
                visit.discard(board[nx][ny])
                length-=1
    return ans

print(dfs(0, 0))

처음에 작성한 코드

너무 쉽게 풀었다 했더니 시간초과 ㅠ.ㅠ

정답 비율이 29.112%인 이유가 있구나 😅

in 때문에 시간초과 나는건가?!

 

 

🐊 다른 사람 풀이

# https://devjin-blog.com/boj-1987-alphabet/
import sys

# 좌, 하, 우, 상
dx=[-1, 0, 1, 0]
dy=[0, -1, 0, 1]

def BFS(x, y) :
    global answer
    q=set([(x, y, board[x][y])])

    while q :
        x, y, ans=q.pop()

        for i in range(4) :
            nx=x+dx[i]
            ny=y+dy[i]

            if((0 <= nx < R) and (0 <= ny < C) and (board[nx][ny] not in ans)) :
                q.add((nx, ny, ans+board[nx][ny]))
                answer=max(answer, len(ans)+1)

R, C=map(int, sys.stdin.readline().split())
board=[list(sys.stdin.readline().strip()) for _ in range(R)]

answer=1
BFS(0, 0)
print(answer)

이 문제는 dfs보다 bfs가 더 적합한가보다.

파이썬으로 제출해도 통과한다.

하긴 dfs로 한 곳을 골라서 막힐 때까지 갔다가 다시 되돌아오는 것보다 더 낫다.

근데 보통 bfs 구현할 때 deque를 많이 쓰는데 이 분은 set으로 구현함.

중복을 허용하지 않으려는 의도인 것 같다.

 

 

import java.util.*;
import java.io.*;

public class Main{
    static int R, C, ans;
    static char[][] board;
    static int[][] visit;
    static final int[] dx={0, 0, 1, -1};
    static final int[] dy={1, -1, 0, 0};

    public static void main(String[] args) throws Exception{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());
        R=Integer.parseInt(st.nextToken());
        C=Integer.parseInt(st.nextToken());
        board=new char[R][C];
        visit=new int[R][C];
        for(int i=0; i<R; i++){
            board[i]=br.readLine().toCharArray();
        }

        dfs(0, 0, 1 << board[0][0]-'A', 1);
        System.out.println(ans);
    }

    public static void dfs(int x, int y, int bit, int cnt){
        if(visit[x][y] == bit) return;
        visit[x][y]=bit;
        ans=Math.max(ans, cnt);
        for(int i=0; i<4; i++){
            int nx=x+dx[i];
            int ny=y+dy[i];
            if(nx<0 || ny<0 || nx==R || ny==C || (bit&(1<<board[nx][ny]-'A')) != 0) continue;
            dfs(nx, ny, bit | (1<<board[nx][ny]-'A'), cnt+1);
        }
    }
}

비트마스크로 문자 포함 여부를 판단한다.

신박한 풀이다👍

visit 안 써도 통과한다.

하지만, 성능 차이가 있기 때문에 visit을 쓰는 게 더 빠름

 

 

 

문제 출처 👉 백준

반응형

'coding test' 카테고리의 다른 글

[파이썬, Java] 11403. 경로 찾기  (0) 2021.10.08
[파이썬, Java] 1707. 이분 그래프  (0) 2021.10.07
[파이썬] 2098. 외판원순회  (0) 2021.10.06
[파이썬] 11723. 집합  (0) 2021.10.04
[파이썬, Java] 1102. 발전소  (0) 2021.10.03