알고리즘/백준

백준 21608 (상어 초등학교) - java

김다미김태리신시아 2023. 2. 20. 22:04

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

 

21608번: 상어 초등학교

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

www.acmicpc.net

import java.io.*;
import java.util.*;

public class Main {
    static int[] dx = {0,0,-1,1}; // 인접한 칸
    static int[] dy = {1,-1,0,0};
    static int[][] board = new int[21][21]; // 학생 책상 좌표계
    static int n = 0;
    static Queue<student> q = new LinkedList<>(); // 학생 정보 큐
    static Queue<point> sq = new LinkedList<>(); // 만족도 측정에 사용할 큐

    static int result = 0; // 총 만족도
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");

        n = Integer.parseInt(st.nextToken());

        for(int i = 1;i<=n*n;i++)
        {
            st = new StringTokenizer(br.readLine(), " ");
            int num = Integer.parseInt(st.nextToken());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            int d = Integer.parseInt(st.nextToken());
            q.add(new student(num,a,b,c,d));
        }

        where(); // 자리 배치

        score(); // 만족도 점수 측정
        System.out.println(result); // 총 만족도 출력

        br.close();
    }
    // 만족도 점수 측정
    static void score()
    {
        while(!sq.isEmpty())
        {
            point cur = sq.poll();
            int num = 0;
            for(int i=0;i<4;i++)
            {
                int nx = cur.x+dx[i];
                int ny = cur.y+dy[i];

                if(nx>=1&&nx<=n&&ny>=1&&ny<=n)
                {
                    if(board[nx][ny]==cur.like[0]||board[nx][ny]==cur.like[1]||board[nx][ny]==cur.like[2]||board[nx][ny]==cur.like[3])
                    {
                        num++; // 인접한 좌표에 좋아하는 학생의 수 조사
                    }
                }
            }
            
            /*학생의 수에 따른 점수 추가*/
            if(num==1)
            {
                result = result + 1;
            }
            else if(num==2)
            {
                result = result + 10;
            }
            else if(num==3)
            {
                result = result + 100;
            }
            else if(num==4)
            {
                result = result + 1000;
            }
        }
    }
    
    // 자리 배치하는 함수
    static void where()
    {
        while(!q.isEmpty())
        {
            student cur = q.poll();
            int like = 0; // 학생이 좋아하는 학생과 인접한 수
            int empty = 0; // 인접한 위치에 비어있는 자리의 수
            int nx = -1;
            int ny = -1;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    int tempty = 0; // 측정 비어있는 자리 수
                    int tlike = 0; // 측정 좋아하는 학생의 수
                    if(board[i][j]==0)
                    {
                        for(int k=0;k<4;k++)
                        {
                            int cx = i + dx[k]; // 인접한 자리의 좌표
                            int cy = j + dy[k];

                            if(cx>=1&&cx<=n&&cy>=1&&cy<=n)
                            {
                                if(board[cx][cy]==0) // 비어있다면
                                {
                                    tempty++;
                                }

                                else if(board[cx][cy]==cur.like[0]||board[cx][cy]==cur.like[1]||board[cx][cy]==cur.like[2]||board[cx][cy]==cur.like[3])
                                {
                                    tlike++; // 좋아하는 학생이라면
                                }
                            }
                        }
                        /*
                            우선순위
                            1. 좋아하는
                            2. 비어있는
                        */
                        if(tlike>like)
                        {
                            like = tlike;
                            empty = tempty;
                            nx = i;
                            ny = j;
                        }
                        else if(tlike==like)
                        {
                            if(tempty>empty)
                            {
                                like = tlike;
                                empty = tempty;
                                nx = i;
                                ny = j;
                            }
                        }
                    }
                }
            }
            // 위 조건에 만족하는 자리가 있다면
            if(nx!=-1&&ny!=-1)
            {
                board[nx][ny] = cur.num; // 자리 배치
                sq.add(new point(nx,ny,cur.like)); // 만족도 측정 큐에 추가
            }
            // 인접한 자리에 좋아하는 학생이나 비어있는 자리가 없는 경우 (낮은 행, 낮은 열 우선순위로 배치)
            else if(nx==-1&&ny==-1)
            {
                for1 : for(int i=1;i<=n;i++)
                {
                    for(int j=1;j<=n;j++)
                    {
                        if(board[i][j]==0)
                        {
                            board[i][j]=cur.num;
                            sq.add(new point(i,j,cur.like));
                            break for1; // 작은 행 , 작은 열 우선순위에 의해 자리를 찾은 경우 바로 반복문 종료
                        }
                    }
                }
            }

        }
    }
}
class student
{
    int num; // 학생의 번호
    int[] like = new int[4]; // 학생이 좋아하는 4명의 학생

    student(int num,int a,int b,int c,int d)
    {
        this.num = num;
        like[0] = a;
        like[1] = b;
        like[2] = c;
        like[3] = d;
    }
}

class point
{
    int x; // 학생의 행 좌표
    int y; // 학생의 열 좌표
    int[] like; // 학생이 좋아하는 4명의 학생

    point(int x,int y,int[] like)
    {
        this.x = x;
        this.y = y;
        this.like = like;
    }
}