Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- 알고리즘
- BFS
- 엘라스틱서치
- 우선순위큐
- 백준코딩테스트
- 네트워크플로우
- 01BFS
- deque
- 다익스트라
- java
- PS
- COSPROJAVA1급
- spring
- 재귀함수
- 취득후기
- QUICKSTARTGUIDE
- 이젠 골드구현도 어렵네..
- DFS
- 세그먼트트리
- dp
- 시뮬레이션
- 완전탐색
- 백준
- GatherTown
- 다이나믹프로그래밍
- 자바PS
- COSPRO
- 게더타운시작
- YBMCOS
- 구현
Archives
- Today
- Total
공부공간
BOJ - 21609 ) 상어 중학교 본문






https://www.acmicpc.net/problem/21609
21609번: 상어 중학교
상어 중학교의 코딩 동아리에서 게임을 만들었다. 이 게임은 크기가 N×N인 격자에서 진행되고, 초기에 격자의 모든 칸에는 블록이 하나씩 들어있고, 블록은 검은색 블록, 무지개 블록, 일반 블록
www.acmicpc.net
매번 가장큰 size를 가진 일반 블록을 찾기위해 NXN을 탐색한다.
(사이즈가 같은경우는 무지개 블록이, 무지개블록이 같은경우는 대표블록의 Y,X값을 참조)
해당 블록이 그룹이 되는 조건을 BFS를 진행하며 확인해준다. ( size가 1이면 그룹이 될 수 없다 )
또한, 점수를 획득할 그룹이 지정되면 반시계반향으로 돌리는 로직과 ( y,x -> 한변의 길이-x,y )
중력을 받아서 아래로 내려오는 로직을 미리 구현해 놓으면, 필요할 때에 호출하여 사용하면된다.
구현문제는 비슷한 유형 ( 시계/반시계 회전, 특정 조건으로 배열 새로제작 )을 띄기 때문에
양치기로 구현 속도를 빠르게 줄일 수 있다.
package algorithm_2022;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class boj_21609 {
public static int ignore =0;
public static class node{
int size;
int rainbow;
int RepreY;
int RepreX;
boolean isGroup;
ArrayList<int[]> coord;
public node() {
size=0; rainbow=0; RepreY=0; RepreX=0; isGroup=false;
coord = new ArrayList<>();
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
ignore = M+1;
boolean isContinue = true;
int [][] dir = {{1,0},{-1,0},{0,1},{0,-1}};
ArrayDeque<int []> dq = new ArrayDeque<>();
PriorityQueue<node> pq = new PriorityQueue<>(new Comparator<node>() {
@Override
public int compare(node o1, node o2) {
// 넓이,무지개 블록수, 대표블록의 행, 대표블록의 열
if(o1.size>o2.size) return -1;
else if(o1.size<o2.size) return 1;
else {
if(o1.rainbow>o2.rainbow) return -1;
else if(o1.rainbow<o2.rainbow) return 1;
else {
if(o1.RepreY>o2.RepreY) return -1;
else if(o1.RepreY<o2.RepreY) return 1;
else {
if(o1.RepreX>o2.RepreX) return -1;
else if(o1.RepreX<o2.RepreX) return 1;
else return 0;
}
}
}
}
});
int map[][] = new int[N][N];
int answer =0;
for(int y=0;y<N;y++) {st = new StringTokenizer(br.readLine()); for(int x=0;x<N;x++) {map[y][x] = Integer.parseInt(st.nextToken());}}
// end of input
while(isContinue) {
// 방문 체크
boolean isVisit[][] = new boolean[N][N];
node n = new node();
for(int y=0;y<N;y++) {
for(int x=0;x<N;x++) {
if(map[y][x]!=0 && map[y][x]!=-1&& !isVisit[y][x] && map[y][x]!=ignore) {
// bfs
n = new node();
n.size=0;
n.rainbow=0;
n.RepreY = -1;
n.RepreX = -1;
dq.clear();
dq.add(new int[] {y,x,map[y][x]});
isVisit[y][x] = true;
while(!dq.isEmpty()) {
int now[] = dq.poll();
int nowy = now[0];
int nowx = now[1];
int nowc = now[2];
n.size++;
if(n.size>=2&&!n.isGroup) {
n.isGroup = true;
} else if(n.size==1){
// 작은것들이 기준블록의 대상이됨
n.RepreY=y;
n.RepreX=x;
n.coord.add(new int[] {y,x});
}
for(int i=0;i<4;i++) {
int nexty=nowy +dir[i][0];
int nextx=nowx +dir[i][1];
if(nexty>=0&&nextx>=0&&nexty<N&&nextx<N) {
if(map[nexty][nextx]!=-1 || map[nexty][nextx] !=ignore) {
if(map[nexty][nextx]==0 && !isRainBow(n.coord,nexty,nextx)) {
n.rainbow++;
dq.add(new int[] {nexty,nextx,nowc});
n.coord.add(new int[] {nexty,nextx});
} else {
if(!isVisit[nexty][nextx] && map[nexty][nextx] == nowc) {
isVisit[nexty][nextx] = true;
dq.add(new int[] {nexty,nextx,nowc});
n.coord.add(new int[] {nexty,nextx});
if(n.RepreY > nexty) {
n.RepreY = n.RepreY > nexty ? nexty : n.RepreY;
n.RepreX = nextx;
} else if(n.RepreY==nexty) {
n.RepreX = n.RepreX > nextx ? nextx : n.RepreX;
}
}
}
}
}
}
}
if(n.isGroup) {
pq.add(n);
}
}
}
}
if(pq.size()==0) {
isContinue = false;
break;
} else {
isContinue = true;
n =pq.poll();
// pq의 맨 처음하나를 ignore 처리하고
answer += (n.size)*(n.size);
for ( int[] co : n.coord) {
map[co[0]][co[1]] = ignore;
}
pq.clear();
}
map = gravity(map);
map = autoclockwise(map);
map = gravity(map);
}
System.out.println(answer);
}
private static boolean isRainBow(ArrayList<int[]> coord, int nexty, int nextx) {
for (int[] is : coord) {if(is[0]==nexty&&is[1]==nextx) return true;}
return false;
}
public static int[][] gravity(int [][] map){
// 검정블록은 움직이지 않는다.
int len = map.length;
int rMap[][] = new int[len][len];
for(int y=0;y<len;y++) for(int x=0;x<len;x++) rMap[y][x] = ignore;
for(int x=0;x<len;x++) {
for(int y=len-1;y>=0;y--) {
if(map[y][x]==ignore || map[y][x]== -1) {
rMap[y][x] = map[y][x];
} else {
// 일반이거나 무지개
if(y==len-1) {
rMap[y][x] = map[y][x];
} else {
// 맨바닥이면, 그냥 넣고
// 아니면, 검정을 만나거나 다른값을 만날때까지 현재에서 위로 찾음
int nexty = y+1;
for(;nexty<len;nexty++) {
if(rMap[nexty][x]!=ignore) {
break;
}
}
rMap[--nexty][x] = map[y][x];
}
}
}
}
return rMap;
}
public static int[][] autoclockwise(int [][]map){
// 반시계
int len = map.length;
int rMap[][] = new int[len][len];
for(int y=0;y<len;y++) {
for(int x=0;x<len;x++) {
rMap[len-1-x][y] = map[y][x];
}
}
return rMap;
}
}

'알고리즘 > 구현,시뮬' 카테고리의 다른 글
BOJ - 25306 ) 연속 XOR (0) | 2022.06.29 |
---|---|
BOJ - 2559 ) 수열 (0) | 2022.06.27 |
BOJ - 2493 ) 탑 (0) | 2022.05.11 |
BOJ - 21608 ) 상어 초등학교 (2) | 2022.04.20 |
BOJ - 1780 ) 종이의 개수 (0) | 2022.03.09 |