처음 이 문제를 그냥 BFS로 풀려고 하니 답이 안나왔다. 왜냐하면 대륙1, 대륙2, 대륙3은 서로 다른 대륙이기에 동시에 진행해버리면 서로 서로에게 가까워지면서 실제 시간보다 빠르게 나오기때문이다. 독립적인 실행이 가능하게 해야했다. 즉, 대륙1에서만 BFS를 진행하고 그다음엔 대륙2에서 BFS를 진행하는.. 식으로 해야했다
그런데.. 한대륙에서만 bfs를 진행한다고 하더라도 다른 좌표(r,c)에서의 bfs 진행 결과가 현재 좌표 (x,y)에 영향을 미치면 제대로 된 결과가 안나올 것 같았다.
static int bfs(int r, int c,int cnt){
int result=0;
Queue<Point> q = new LinkedList<>();
q.add(new Point(r,c));
while(!q.isEmpty()){
int size = q.size();
while(size>0){
Point cur = q.poll();
visited[cur.r][cur.c] = true;
for(int i=0;i<4;i++){
int rr = cur.r + dx[i];
int cc = cur.c + dy[i];
if(rr>=n||cc>=n||rr<0||cc<0||visited[rr][cc]) continue;
if(map[rr][cc]==0){
visited[rr][cc] = true;
q.add(new Point(rr,cc));
}else if(map[rr][cc] == cnt){
visited[rr][cc] = true;
}else{
return result;
}
}
size--;
}
result++;
}
return -1;
}
//main함수
for(int i =0; i<n; i++){
for(int j = 0; j<n; j++){
if(map[i][j] == 0||visited[i][j]) continue;
min = Math.min(min,bfs(i,j,map[i][j]));
}
}
import java.io.*;
import java.util.LinkedList;
import java.util.Queue;
public class Main {
static int n;
static int dx[] = {0,0,1,-1};
static int dy[] = {1,-1,0,0};
static int map[][];
static boolean visited[][];
static int bfs(int r, int c,int cnt){
int result=0;
visited = new boolean[n][n];
Queue<Point> q = new LinkedList<>();
q.add(new Point(r,c));
while(!q.isEmpty()){
int size = q.size();
while(size>0){
Point cur = q.poll();
visited[cur.r][cur.c] = true;
for(int i=0;i<4;i++){
int rr = cur.r + dx[i];
int cc = cur.c + dy[i];
if(rr>=n||cc>=n||rr<0||cc<0||visited[rr][cc]) continue;
if(map[rr][cc]==0){
visited[rr][cc] = true;
q.add(new Point(rr,cc));
}else if(map[rr][cc] == cnt){
visited[rr][cc] = true;
}else{
return result;
}
}
size--;
}
result++;
}
return Integer.MAX_VALUE;
}
//map에 있는 대륙의 개수를 count한다
static int count(){
temp = new boolean[n][n];
int result = 0;
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
if(!temp[i][j] && map[i][j]==1) {
dfs(i,j, ++result);
}
}
}
return result;
}
static void dfs(int r, int c, int k){
temp[r][c] = true;
map[r][c] = k;
for(int i=0;i<4;i++){
int rr = r + dx[i];
int cc = c + dy[i];
if(rr>=n||cc>=n||rr<0||cc<0||temp[rr][cc] ||map[rr][cc]==0) continue;
dfs(rr,cc, k);
}
}
static class Point{
int r;
int c;
Point(int r, int c){
this.r=r;
this.c=c;
}
}
static boolean temp[][];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
map = new int[n][n];
for(int i=0;i<n;i++) {
String input2[]= br.readLine().split(" ");
for(int j=0;j<n;j++) {
map[i][j] = Integer.parseInt(input2[j]);
}
}
//각섬을 섬1, 섬2, 섬3으로 구분한다
count();
int min = Integer.MAX_VALUE;
for(int i =0; i<n; i++){
for(int j = 0; j<n; j++){
if(map[i][j] == 0) continue;
//한점에 대해서 bfs 탐색을한다
//한점에 대해서만 탐색하니 여러 점에 의한 탐색 충돌이 안발생한다
min = Math.min(min,bfs(i,j,map[i][j]));
}
}
//가장 짧은 다리 출력
System.out.println(min);
}
}
정답으로 처리가 되긴했지만 다른 풀이에 비해 메모리를 많이 사용하고 있었다
추가적으로 방문배열을 하나 더 선언해서 내가 탐색한 대륙1에 대해 모두 방문처리를 해주는 식으로 코드를 짜면 메모리를 반절정도 덜 사용하게 된다
//main
temp = new boolean[n][n];
for(int i =0; i<n; i++){
for(int j = 0; j<n; j++){
if(map[i][j] == 0||temp[i][j]) continue;
//한점에 대해서 bfs 탐색을한다
//한점에 대해서만 탐색하니 여러 점에 의한 탐색 충돌이 안발생한다
temp[i][j] = true;
min = Math.min(min,bfs(i,j,map[i][j]));
}
}
static int bfs(int r, int c,int cnt){
//한점에서만 bfs를 진행할거기때문에 visited배열을 매번 초기화 해주어야한다
temp[r][c] = true;
visited = new boolean[n][n];
Queue<Point> q = new LinkedList<>();
q.add(new Point(r,c,0));
while(!q.isEmpty()){
//size 만큼 반복해주는 행위 = class에 len이라는 필드추가하는것과 같음
Point cur = q.poll();
//1x1의 예외상황을 처리하기 위함
visited[cur.r][cur.c] = true;
for(int i=0;i<4;i++){
int rr = cur.r + dx[i];
int cc = cur.c + dy[i];
if(rr>=n||cc>=n||rr<0||cc<0||visited[rr][cc]) continue;
//방문안한 점인데 0이면 그쪽으로 탐색을 진행한다. 그러다가 다른 지역을 만나면 result(time) 을 반환한다
if(map[rr][cc]==0){
visited[rr][cc] = true;
q.add(new Point(rr,cc,cur.t+1));
//map[rr][cc]가 0 도 아니고 cnt도 아니라면 다른 대륙이다
//time의 최소시간을 return해주자
}else if(map[rr][cc] != cnt){
return cur.t;
}else{
//추가 이거때문에 ..
temp[rr][cc] = true;
}
}
}
return Integer.MAX_VALUE;
}
개발자로서 성장하는 데 큰 도움이 된 글이었습니다. 감사합니다.