gun0317   5년 전


백트레킹으로 모든 점에서 시작점을 기준으로, 한번 방문했던 시작점은 0으로 돌리는 것이아닌 다른 임의의 숫자(3)으로 만들어서 해당 부분에 중복 접근하지 못하게 하였습니다.

그 후 상하좌우 순으로 인접한 블록이 있는지 여부를 검사하는 validity 함수를 사용하여 가능한 테트로미노의 모든 조합을 구하였습니다.

구한 조합으로 마스킹을 하여 ans를 업데이트하는 calculate 함수를 사용하였습니다.

디버깅을 하면서 보니 정사각형 모양이 중복으로 발생하긴 하지만 2~3회만 만드는 것으로 보여 중복 제거가 문제인지는 잘 모르겠습니다.

채점 0%에서 시간초과가 납니다.  예제와  https://www.acmicpc.net/board/view/32956 에 jaeyoon8783님이 올려주신 케이스 및 질문 게시판 몇 개 반례는 모두 통과가 됩니다. 아무래도 크기가 큰 경우에 시간초과가 나는 듯 한데 어떻게 해결해야할 지 모르겠습니다 ㅠ


디버깅 시 아래와 같이 1이 4개가 조합되면 calculate함수를 실행합니다. 

이미 지나온 시작점은 3으로 표시하여 1이 표시되지 않게 하였습니다.

cb094cfd-2512-42e8-aed7-485ec5142852

다음 번 조합입니다.

48251b99-7fdb-4379-9cbf-10a93c19e325

읽어주셔서 감사합니다.

djm03178   5년 전

매번 back함수가 재귀호출될 때마다 최대 500*500개의 칸을 보게 되는데, 그럴 필요가 있을까요?

validity를 통해 그 칸에 인접한 방문 칸이 있는지를 보고 있는데, 실제로 유효한 칸의 개수는 많아야 8칸 뿐이고 (depth가 3일 때 ㅁㅁㅁ 모양), 나머지 249992칸은 어차피 유효하지 않은 칸인데도 불필요하게 검사를 하게 됩니다.

어떻게 하면 그런 칸들을 아예 보지 않고 백트래킹을 수행할 수 있을지 생각해 보세요.

gun0317   5년 전

djm03178님 답변 감사합니다. 코드 수정하였습니다.(수정된 부분: 52~54, 63, 78~85 줄)

제가 63번 줄 'if(depth ==0)'의 위치를 잘못 두었던 것 같아 올바른 위치로 옮겼습니다. 그리고 maxR,maxC 등을 사용하여 본인 근처 4칸만 탐색을 하도록 해 보았으나 여전히 시간초과가 납니다. 500*500칸을 보는 경우는 없어진 것 같은데 여전히 시간초과가 나는 이유를 잘 모르겠습니다..

djm03178   5년 전

여전히 16x16칸을 보는 것이 비효율적이기는 하지만, 이제 여기보다 더 문제인 곳은 calculate 함수입니다. 네 칸을 고를 때마다 25만칸씩을 체크해야 하므로 매우 비효율적입니다. 재귀 호출을 할 때마다 어떤 칸을 체크했는지를 미리 모아두면 이렇게 25만 칸을 calculate 함수가 다시 볼 필요가 없습니다.

참고로, 현재 코드가 200x200 칸에서 27번째 줄의 루프가 도는 횟수는 이미 168억이나 됩니다.

gun0317   5년 전

djm03178 님 상세한 답변 감사합니다. 문제 풀기만 급급해서 calculate 부분은 볼 생각을 못 했었는데 이부분을 말씀하신대로 vector에 추가하여 접근하니 비록 느리지만 정답처리 되었습니다. 덕분에 많이 배워갑니다. 좋은 하루 되세요!!

댓글을 작성하려면 로그인해야 합니다.