본문 바로가기

백준/BFS

아기 상어

728x90

www.acmicpc.net/problem/16236

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가

www.acmicpc.net

#include<iostream>
#include <vector>
#include <queue>


using namespace std;
int n;
int arr[21][21];
int dx[] = { -1,1,0,0 };
int dy[] = { 0,0,-1,1 };

bool check[21][21];

typedef struct{
	
	int x;
	int y;
	int sz;
	int t;
	int cnt;

}info;

int bfs(info &baby, int tx, int ty) { //참조연산자가 훨씬 편하니까 참조연산자 쓸것
	
	queue<info>q;
	q.push(baby);
	memset(check, false, sizeof(check));
	vector<int>v;

	while (!q.empty()) {

		int x = q.front().x;
		int y = q.front().y;
		int sz = q.front().sz;
		int t = q.front().t;
		int cnt = q.front().cnt;
		
		q.pop();
		if (x == tx && y == ty) { baby = { x,y,sz,t,cnt };  return t; }

		for (int i = 0; i < 4; i++) {
			int nx = x + dx[i];
			int ny = y + dy[i];
			if (nx < n && nx >= 0 && ny < n && ny >= 0) {
				
				if (arr[nx][ny] < sz && arr[nx][ny]!=0&& check[nx][ny]==false ) {
					
					if (sz == cnt + 1) { q.push({ nx, ny, sz + 1, t + 1,0 }); }
					else { q.push({ nx, ny, sz, t + 1,cnt+1 }); }
					check[nx][ny] = true;
				}
				else if (arr[nx][ny] == sz || arr[nx][ny] == 0) { //첨에 sz와 같을경우와 0일 경우를 안따짐
					if (check[nx][ny] == false) {
						q.push({ nx, ny, sz, t+1 ,cnt });
						check[nx][ny] = true;
					}
				}
			
			
			}
		
		}
	}
	return -1;

}


int main() {

	cin >> n;
	
	info baby;
	vector<info>fish;

	memset(check, false, sizeof(check));

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> arr[i][j];
			if (arr[i][j] == 9) {
				baby.x = i;
				baby.y = j;
				baby.sz = 2;
				baby.t = 0;
				baby.cnt = 0;
			}
			if (arr[i][j] >= 1 && arr[i][j] <= 6) {
				fish.push_back({i,j,arr[i][j],0,0});
			}
		}
	}




	while (!fish.empty()) {

		if (fish.size() == 1) {
			info finfo = fish.front();
			if (finfo.sz < baby.sz) {
				bfs(baby, finfo.x, finfo.y);

			}
			fish.pop_back();
		}
		else {

			int mindist = 9999;
			info minfish;
			info minbaby = baby;
			int minidx = -1;
	
			for (int i = 0; i < fish.size(); i++) {
				info test;
				info f = fish[i];
		
				test = baby;

				if (f.sz < baby.sz) {
				
					int aftersize = bfs(test, f.x, f.y);
					if (aftersize == -1) { continue; }
					int dist = aftersize;
					if (mindist > dist) {
						minfish = f;
						minbaby = test;
						minidx = i;
						mindist = dist;
			
					}
					else if (mindist == dist ) {
						if (minfish.x > f.x) {
							minfish = f;
							minbaby = test;
							minidx = i;
							mindist = dist;
			
						}
						else if (minfish.x == f.x) {
							if (minfish.y > f.y) {
								minfish = f;
								minbaby = test;
								minidx = i;
								mindist = dist;
			
							}
						}
					}
				}
			}

			if (minidx != -1) {
	
				fish.erase(fish.begin() + minidx);
				arr[baby.x][baby.y] = 0;
				arr[minbaby.x][minbaby.y] = 9; // 마지막에 이거 시작지점 안바꿔줘서 에러남
				baby = minbaby;
				arr[minfish.x][minfish.y] = 0;
				

			}
			else {
				break;
			}
		}

	}

	cout << baby.t << endl;




	

}

 

<JAVA>

package Samsung;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.StringTokenizer;

public class 아기상어 {

	static int n;
	static int[][]arr;
	
	static int[] dx = {-1,1,0,0};
	static int[] dy = {0,0,1,-1};
	
	static class Pair implements Comparable<Pair>{
		
		int x, y;
		
		Pair(int x, int y){
		this.x = x;
		this.y = y;
		}
		
		public int compareTo(Pair o) {
			
			if(this.x == o.x) {
				return this.y-o.y;
			}
			
			return this.x-o.x;
			
		}
		
	}
	
	
	public static boolean cango(int x, int y) {
		return x>=0 && x<n && y>=0 && y<n;
	}
	
	
	
	static int time=0; 
	
	public static Pair bfs(int bposx , int bposy, int bweight) { //아기상어의 위치와 무게를 넣어준다.
		
		
		boolean[][] check  =new boolean[n][n];
		Queue<Pair>q = new LinkedList<>();
		PriorityQueue<Pair> pq = new PriorityQueue<>();
		q.add(new Pair(bposx,bposy));
		
		check[bposx][bposy] = true;
		
		int dist =0;
		boolean tg = false;	
		
		Pair nofish = new Pair(-1,-1);
		
		int cx = n+1; //가장가까운 상어의 위치 저장하기 위한 변수
		int cy = n+1;
		
		while(!q.isEmpty()) {
		
		int sz = q.size();
		
		for(int t=0; t<sz;t++) {
			
			Pair p = q.poll();
			int x = p.x;
			int y = p.y;
	
			
			for(int i=0; i<4; i++) {
				
				int nx = x+dx[i];
				int ny = y+dy[i];
				if(cango(nx,ny)&& !check[nx][ny] && bweight>=arr[nx][ny] ) {
					
					//큐에 넣고 빼서 가장 위 가장 왼에 있는지 검사하면안됨(그럼 탐색할 갯수가 너무 많아져서 시간초과남)
					//바로 우선순위 큐에 넣어주어서 while문을 빠져나가게 한다.
					if(arr[nx][ny]!=0 && arr[nx][ny]<bweight ) {
						tg=true;//while문 빠져나가게 하는 토글변수 
						pq.add(new Pair(nx,ny)); //priority queue 
					}
					check[nx][ny]=true;
					q.add(new Pair(nx,ny));
				}
				
			}
			
		}
		
		
		
		dist++; //방문한 거리를 증가 시키기
		if(tg) {
			time=dist; //가장 짧은시간 저장
			cx=pq.peek().x; //가장 짧은시간 때의 x값
			cy=pq.peek().y; //가장 짧은시간 때의 y값
			break;
		}
		}
		
		if(!tg) return nofish;
		
		return new Pair(cx,cy);
		
		
		
		
	}
	

	
	
	
	
	public static int simulate(int bposx , int bposy, int bweight) {
		int plusf =0;
		int totalt = 0;
		while(true) {
			
			time=0;//전역변수니까 초기화하고 시작
			Pair fpos = bfs(bposx,bposy,bweight); //가장 가까운 물고기중 가장 위,가장 오른쪽에 있는것을 bfs로찾는다
			
			int x = fpos.x;
			int y = fpos.y;
			if(x==-1 && y==-1) {break;} //잡아먹을 물고기가 더이상 없을 때
			
			plusf++;//잡아먹은 물고기수 증가
			arr[bposx][bposy]=0;  // 상어의 기존 위치는 빈 곳으로
			bposx =x; //상어 위치 변경
			bposy=y;
			
			arr[bposx][bposy]=9; //상어가 있는 곳을 9로저장
			
			totalt +=time; //움직인시간을 더해준다
			
			if(plusf==bweight) { //
				bweight+=1;
				plusf=0;
			}
		}
		
		return totalt;
	}
	
	
	

	public static void main(String[] args) throws NumberFormatException, IOException {
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		n = Integer.parseInt(br.readLine());
		arr = new int [n][n];
		
		StringTokenizer st;
		
		int bposx =0, bposy=0, bweight=2;
		for(int i=0; i<n; i++) {
		st= new StringTokenizer(br.readLine());
		for(int j=0; j<n; j++) {
		
			arr[i][j]= Integer.parseInt(st.nextToken());
		
			if(arr[i][j]==9) { // 초기 아기상어의 위치와 무게 저장
				bposx = i;
				bposy = j;
				bweight =2;
						
			}
		
		}
		}
		
		int answer = simulate(bposx, bposy,bweight);
		
		System.out.println(answer);
		
	}
	
	
	
}

'백준 > BFS' 카테고리의 다른 글

스타트링크  (0) 2021.03.25
4연산  (0) 2021.03.16
움직이는 미로탈출  (0) 2021.03.09
벽부수고 이동하기3  (0) 2021.03.08
벽부수고 이동하기2  (0) 2021.03.07