Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions Essential/21608_상어초등학교/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

public class Main {
static int [][] graph;
static int N; // 반의 크기 (N*N)
static int[] dr={-1,1,0,0};
static int[] dc={0,0,-1,1};
static Map<Integer,int[]> love; //<학생번호, 학생이 좋아하는 친구들의 번호>
static class Seat implements Comparable<Seat>{ //자리에 대한 정보
int r,c, empty, friend;

public Seat(int r, int c, int empty, int friend) {
this.r = r;
this.c = c;
this.empty = empty;
this.friend = friend;
}

@Override
public int compareTo(Seat o) {
//1.친구가 많은 자리 2.빈칸이 많은자리 3. 행이 작은 자리 4. 열이 작은 자리
if(this.friend == o.friend){
if(this.empty == o.empty){
if(this.r == o.r){
return this.c - o.c; //친구, 빈 칸, 행이 같다면 열로 오름차순
}
return this.r - o.r; //친구, 빈 칸이 같다면 열로 오름차순
}
return o.empty - this.empty; //친구가 같다면 빈칸으로 내림차순
}
return o.friend - this.friend; //친구로 내림차순
}

}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
int studentNum= (int)Math.pow(N, 2);
graph = new int[N][N];
love = new HashMap<>();

for(int i=0; i<studentNum; i++){
StringTokenizer st = new StringTokenizer(br.readLine());
int student = Integer.parseInt(st.nextToken());
int [] person = new int[4];
for(int j=0; j<4; j++){
int p = Integer.parseInt(st.nextToken());
person[j]=p;
}
love.put(student, person);

putStudentSeat(student); //해당 번호의 학생을 자리 배정
}


System.out.println(getScore()); //최종 스코어 반환


}

static void putStudentSeat(int student){
int [] friends = love.get(student);
Seat seat = null; // 그 사람의 자리
for(int r=0; r<N; r++){
for(int c=0; c<N; c++){ //모든 자리를 돌면서 해당 학생의 앉힐 자리에 대한 정보를 구한다.
if(graph[r][c]!=0) continue; //이미 그 자리에 배정 받은 학생이 있다면 skip
int friendCnt=0;
int emptyCnt=0;

for(int d=0; d<4; d++){ //4방위 탐색
int nr = r+dr[d];
int nc = c+dc[d];
if(nr<0 || nc<0 || nr>=N || nc>= N) continue; //out of range
for(int i=0; i<4; i++){
if(graph[nr][nc]==friends[i]){ //r,c 주변 4방위 중 좋아하는 친구가 있다면
friendCnt++; //좋아하는 친구 +1
}
}
if(graph[nr][nc]==0) emptyCnt++; // 빈 칸이라면 빈칸 +1
}

if(seat == null){
seat = new Seat(r, c, emptyCnt, friendCnt);
}else{
Seat com = new Seat(r, c, emptyCnt, friendCnt);
if(seat.compareTo(com)>0){
seat = com;
}
}
}
}

graph[seat.r][seat.c] =student;
}

static int getScore(){
int score=0;
for(int r=0; r<N; r++){
for(int c=0; c<N; c++){ //모든 칸 순회
int cnt=0;
int [] friends = love.get(graph[r][c]);

for(int d=0; d<4; d++){
int nr = r+dr[d];
int nc = c+dc[d];

if(nr <0 || nc<0|| nr>=N || nc>=N ) continue;

for(int i=0; i<4; i++){
if(graph[nr][nc]==friends[i]){
cnt++; //해당 주위에 좋아하는 친구가 있다면 cnt ++
}
}
}
if(cnt>0){
score+= Math.pow(10, cnt-1); //10의 (cnt-1)제곱을 score에 더해준다.
}
}
}


return score;
}

}
37 changes: 37 additions & 0 deletions Essential/21608_상어초등학교/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## 문제 이해
* 교실은 N*N의 격자 나타낼 수 있고 (r, c)는 r행 c열을 의미한다.
* 학생은 1번부터 N^2번까지 번호가 매겨져 있다.
* 학생의 번호와 그 학생이 좋아하는 학생 4명의 번호가 주어진다.
* 다음과 같은 규칙을 이용해 정해진 순서대로 학생의 자리를 정하려고 한다.
* 한 칸에는 학생 한 명의 자리만 있을 수 있고, |r1 - r2| + |c1 - c2| = 1을 만족하는 두 칸이 (r1, c1)과 (r2, c2)를 인접한다고 한다.

* 1. 비어있는 칸 중에서 좋아하는 학생이 인접한 칸에 가장 많은 칸으로 자리를 정한다.
* 2. 1을 만족하는 칸이 여러 개이면, 인접한 칸 중에서 비어있는 칸이 가장 많은 칸으로 자리를 정한다.
* 3. 2를 만족하는 칸도 여러 개인 경우에는 행의 번호가 가장 작은 칸으로, 그러한 칸도 여러 개이면 열의 번호가 가장 작은 칸으로 자리를 정한다.

* 최종적으로 학생의 만족도를 구한다.
* 학생의 만족도를 구하려면 그 학생과 인접한 칸에 앉은 좋아하는 학생의 수를 구해야 한다.
* 그 값이 0이면 학생의 만족도는 0, 1이면 1, 2이면 10, 3이면 100, 4이면 1000이다.

## 아이디어
1. 완전탐색, Map
2. 자리의 정보에 대한 Class생성. 자리배치 Method 구현.
## 구현
### 상태
* `Seat` : 자리에 대한 정보를 저장할 Class. 자리의 좌표, 자리에 인접한 빈자리의 수, 자리에 인접한 좋아하는 친구의 수를 저장한다.
* `graph` : 현재 교실의 배치 상태(2차원 배열). (0이면 빈자리)
* `love` : HashMap<Integer,int[]> Key : 학생의 번호 , Value : 학생이 좋아하는 학생 번호
* `putStudentSeat` : 학생을 교실에 자리배치 하는 Method
* `getScore` : 만족도를 조사하는 Method


### 탐색
* `putStudentSeat`의 파라미터에 교실에 배치할 학생의 번호를 넘겨준다.
* `freinds` 배열에 해당 학생의 좋아하는 학생들을 넣어준다.
* 전체 좌표를 탐색하며 해당 좌표가 비어있다면, 그 좌표의 주변을 분석하여 empty정보와 friend정보를 `Seat seat`객체에 넣어서 `ArrayList<Seat> seats`에 넣어준다.
* 모든 좌표를 탐색했다면, `Seats`리스트를 문제 조건에 맞게 정렬한다.
* 정렬 후 가장 첫번째 객체 `seat`이 해당 학생의 자리이다.
* 이를 모든 학생에 대하여 진행한다.
* 자리 배치가 끝났다면 `getScore` Method로 최종 만족도를 구한다.
* 모든 좌표에 대하여 인접한 좋아하는 친구의 수를 구하여서 10의 (cnt-1)제곱으로 만족도를 계산하여 `score`에 더해준다.
* 최종 `score`을 반환하여 출력한다.