백준 14500번 테트로미노 (삼성 SW 역량테스트 기출문제)
사용한 알고리즘: 브루스 포스, 구현...?
삼성 기출은 굉장히 구현문제가 많은 것 같습니다.
우리 화이팅 해 봅시다...!
우선 문제에서 주어진 폴리오미노(?)를 대칭, 회전 모두 가능하다 했기에
주어진 세가지 조건
1. 정사각형은 겹치지 않는다.
2. 도형은 모두 연결되어 있어야 한다.
3. 정사각형 끼리는 변으로 연결되어야 한다.
를 기준으로 생각했습니다.
먼저 (0,0) 사각형부터 끝 지점 까지 모든 사각형을 훑었습니다. (브루스 포스 - 완전탐색)
단 i 번째 사각형을 볼 때 좌,우,아래 사각형만 보고 사각형은 보지 않는 식으로 중첩을 최소화 하려고 했습니다.
함수를 하나 만들고 추가 블록 개수를 저장 (처음엔 4개) 하며 재귀형식으로 함수를 돌렸습니다.
(1) i 번째 사각형에서 추가 블록 개수가 (자신 제외) i번째 사각형이 맞닿아 있는 (아직 쓰지않은) 사각형 개수보다 작은 경우
(2) 추가 블록 개수가 1 보다 큰경우 ( 추가 블록 개수가 1 인 경우는 (1)과정에서 이미 생각)
아래 사각형으로 이동, 왼쪽 사각형으로 이동, 오른쪽 사각형으로 이동
위와같이 크게 2개의 과정으로 생각하여,
함수를 돌릴 때 과정(1) 의 경우는 그냥 노가다 해서 구했고,
(2) 의 경우는 재귀형태로 구해서
각 과정마다 구하고자 하는 최대값을 최신화 해 주었습니다.
푸는 방식 자체는 어렵지 않고, 다양한 풀이가 있을 거라고 생각됩니다.
(물론 저보다 훨씬 깔끔하게 푸는 분들도 많을 겁니다..!!)
포인트는 누가 실수를 안하고 구현을 하느냐 였던 문제인 것 같습니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
// 재귀, 브루트 포스 | |
int N, M, ans, arr[501][501]; | |
bool visited[501][501]; | |
// 위로 올라가진 않을것입니다. | |
void MaxAns(int x, int y, int cnt, int temp){ | |
temp+=arr[x][y]; | |
cnt--; | |
// 인접 사각형 보는 경우 | |
int near = 0; | |
if(x+1<N && !visited[x+1][y]) near++; | |
if(y-1>=0 && !visited[x][y-1]) near++; | |
if(y+1<M && !visited[x][y+1]) near++; | |
if(near>=cnt){ | |
int ttt = 0; | |
if(cnt==3){ | |
ttt+=(arr[x+1][y]+arr[x][y-1]+arr[x][y+1]); | |
ans=max(ans, temp+ttt); | |
} | |
else if(cnt==2){ | |
if(near==2){ | |
if(x+1<N && !visited[x+1][y]) ttt+=arr[x+1][y]; | |
if(y-1>=0 && !visited[x][y-1]) ttt+=arr[x][y-1]; | |
if(y+1<M && !visited[x][y+1]) ttt+=arr[x][y+1]; | |
ans=max(ans,temp+ttt); | |
} | |
else if(near==3){ | |
ttt+=(arr[x+1][y]+arr[x][y-1]); | |
ans=max(ans,temp+ttt); | |
ttt=0; | |
ttt+=(arr[x+1][y]+arr[x][y+1]); | |
ans=max(ans,temp+ttt); | |
ttt=0; | |
ttt+=(arr[x][y-1]+arr[x][y+1]); | |
ans=max(ans,temp+ttt); | |
ttt=0; | |
} | |
} | |
else if(cnt==1){ | |
if(x+1<N && !visited[x+1][y]) ttt+=arr[x+1][y]; | |
ans=max(ans,temp+ttt); | |
ttt=0; | |
if(y-1>=0 && !visited[x][y-1]) ttt+=arr[x][y-1]; | |
ans=max(ans,temp+ttt); | |
ttt=0; | |
if(y+1<M && !visited[x][y+1]) ttt+=arr[x][y+1]; | |
ans=max(ans,temp+ttt); | |
} | |
} | |
if(cnt==1) return; | |
// DFS 돌아야 되는 경우 (cnt>1 인 경우) | |
visited[x][y] = true; | |
if(x+1<N && !visited[x+1][y]) MaxAns(x+1,y,cnt,temp); | |
if(y-1>=0 && !visited[x][y-1]) MaxAns(x,y-1,cnt,temp); | |
if(y+1<M && !visited[x][y+1]) MaxAns(x,y+1,cnt,temp); | |
visited[x][y] = false; | |
} | |
int main(){ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); | |
cin >> N >> M; | |
for (int i = 0; i < N; ++i) | |
for (int j = 0; j < M; ++j) | |
cin >> arr[i][j]; | |
for (int i = 0; i < N; ++i){ | |
for (int j = 0; j < M; ++j){ | |
MaxAns(i,j,4,0); | |
} | |
} | |
cout << ans << '\n'; | |
return 0; | |
} |
댓글
댓글 쓰기
긴 글 읽어주셔서 감사합니다.
궁금한게 있으시다면 댓글 달아주세요!