개발/알고리즘

백준 21608번 상어초등학교

dev-yoon-jerry 2021. 6. 7. 22:11

https://www.acmicpc.net/problem/21608

 

21608번: 상어 초등학교

상어 초등학교에는 교실이 하나 있고, 교실은 N×N 크기의 격자로 나타낼 수 있다. 학교에 다니는 학생의 수는 N2명이다. 오늘은 모든 학생의 자리를 정하는 날이다. 학생은 1번부터 N2번까지 번호

www.acmicpc.net

깡 구현문제였는데 실버1치곤 쉽지 않았던 것 같다.

처음부터 학생 클래스를 만들어서 위치, 좋아하는 학생리스트를 넣어줬다면 탐색작업을 더 적게했을텐데.. 못생긴코드

package bj2021_06_07_상어초등학교;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class bj21608 {
	static int N;
	static int [][] seats;
	static List <int[]> like = new ArrayList<>();
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		N = Integer.parseInt(br.readLine());
		seats = new int[N][N];
		for(int n=0;n<N*N;n++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int me = Integer.parseInt(st.nextToken());
			int f1 = Integer.parseInt(st.nextToken());
			int f2 = Integer.parseInt(st.nextToken());
			int f3 = Integer.parseInt(st.nextToken());
			int f4 = Integer.parseInt(st.nextToken());
			int [] friends= {me,f1,f2,f3,f4}; //내번호, 좋아하는사람들 1,2,3,4
			like.add(friends);
			getSeat(n);
		}
		System.out.println(getResult());
	}
	static void getSeat(int index) {
		if(index==0) { //첫번째 학생은 자리고정
			seats[1][1]=like.get(index)[0];
			return;
		}
		int [][][] scores = new int[N][N][2];
		int maxLike=0;
		int maxEmpty=0;
		for(int i=0;i<N;i++) {
			for(int j=0;j<N;j++) {
				if(seats[i][j]!=0) continue;
				scores[i][j]=getScore(index,i,j);
				maxLike = Math.max(maxLike, scores[i][j][0]); 
				maxEmpty = Math.max(maxEmpty, scores[i][j][1]);
			}
		}
		if(maxLike==0 && maxEmpty==0) {
			for(int i=0;i<N;i++) {
				for(int j=0;j<N;j++) {
					if(seats[i][j]==0) {
						seats[i][j]=like.get(index)[0];
						return;
					}
				}
			}

		}
		List <int[]> candidate = new ArrayList<>(); //좋아하는 헉생이 많은 자리
		int maxCandidateEmpty = 0;
		for(int i=0;i<N;i++) {
			for(int j=0;j<N;j++) {
				if(scores[i][j][0]==maxLike) {
					candidate.add(new int[] {i,j,scores[i][j][1]});
					maxCandidateEmpty = Math.max(maxCandidateEmpty, scores[i][j][1]);
				}
			}
		}
		if(candidate.size()==0) { //좋아하는 학생이 많은 자리가 없음 빈자리 많은 곳 선택
			loop: for(int i=0;i<N;i++) {
				for(int j=0;j<N;j++) {
					if(scores[i][j][2]==maxEmpty) {
						seats[i][j]=like.get(index)[0];
						break loop;
					}
				}
			}
		}
		else if(candidate.size()>=2) { // 좋아하는 학생이 많은 자리가 둘이상
			for(int [] c : candidate) {
				if(c[2]==maxCandidateEmpty) {
					seats[c[0]][c[1]]=like.get(index)[0];
					break;
				}
			}
		}
		else { // 좋아하는 학생이 앉은 자리가 유일
			seats[candidate.get(0)[0]][candidate.get(0)[1]]=like.get(index)[0];
		}
		
	}
	static int[] getScore(int index,int i,int j) {
		int [][] next = {{1,0},{-1,0},{0,1},{0,-1}};
		int [] score= {0,0}; //좋아하는 학생수, 빈공간수
		for(int k=0;k<4;k++) {
			int nextI = i+next[k][0];
			int nextJ = j+next[k][1];
			
			if(nextI<0 || nextI>=N) continue;
			if(nextJ<0 || nextJ>=N) continue;
			int person = seats[nextI][nextJ];
			if(person==0) { //앉은 사람없음
				score[1]++;
				continue;
			}
			for(int l=1;l<5;l++) { //앉은 사람이 좋아하는 학생인지 체크
				if(person == like.get(index)[l]) {
					score[0]++;
				}
			}
		}
		return score;
	}
	static int getResult() {
		int result = 0;
		for(int i=0;i<N;i++) {
			for(int j=0;j<N;j++) {
				int now = seats[i][j];
				int index = 0;
				for(int p=0;p<like.size();p++) {
					if(like.get(p)[0]==now) {
						index = p;
						break;
					}
				}
				int score = getScore(index,i,j)[0];
				if(score == 0)
					result+=0;
				if(score == 1)
					result+=1;
				if(score == 2)
					result+=10;
				if(score == 3)
					result+=100;
				if(score == 4)
					result+=1000;
			}
		}
		return result;
	}
}

 

주어진 테스트 케이스 2개로 검사했더니 계속 틀렸습니다가 나와서 다른 테스트케이스를 직접 만들어 테스트했더니 
주변에 좋아하는 학생들이 없는데 앉을 자리가 많은 경우 첫번째 자리에 값이 계속 덮어 씌워지는 오류를 발견할 수 있었다.

4
1 1 2 3 4
2 1 2 3 4
3 1 2 3 4
4 1 2 3 4
5 1 2 3 4
6 1 2 3 4
7 1 2 3 4
8 1 2 3 4
9 1 2 3 4
10 1 2 3 4
11 1 2 3 4
12 1 2 3 4
13 1 2 3 4
14 1 2 3 4
15 1 2 3 4
16 1 2 3 4

답: 48

완성된 배열

13 5 9 14
6 1 2 7
10 3 4 11
15 8 12 16

 

3
1 2 3 4 5
2 1 3 4 5
3 1 2 4 5
4 1 2 3 5
5 1 2 3 4
6 1 2 3 4
7 1 2 3 4
8 1 2 3 4
9 1 2 3 4

답 : 134

 

'개발 > 알고리즘' 카테고리의 다른 글

백준 1062번 가르침  (0) 2021.06.17
백준 9465번 스티커  (0) 2021.06.10
백준 1149번 RGB거리  (0) 2021.06.09
백준 11725번 트리의 부모 찾기  (0) 2021.06.08
백준 2644번 촌수계산  (0) 2021.06.08