๋ฌธ์
๋ฐฐ์ด ์
- ๋ฐฐ์ด ํ์
- ๊ทธ๋ฃนํ DFS
- ๊ทธ๋ฃน๋ณ ์ ์ฅ ๊ณ ๋ฏผ
- ๊ทธ๋ฃน์ ๋ํ ์นด์ดํธ (์กฐํฉ)
- ํ์ง๋ง ๋จ์ํ ์กฐํฉ Combination์ผ๋ก ํ๊ธฐ์ ๋๋ฌด ๋ง์ ๊ฒฝ์ฐ์ ์
- ํ์ํ ์กฐํฉ๋ง ์ ์ ์๋๋ก ์๊ฐํ๊ธฐ
์ฝ๋
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Set;
import java.util.StringTokenizer;
class Group{
int cnt;
int number;
public Group(int cnt, int number) {
this.cnt = cnt;
this.number = number;
}
}
public class Main{
static int N, numOfGroup, answer;
static int[][] board;
static Group[][] marking;
static boolean[][] visited;
static HashMap<Group, Integer> groupAdjCnt;
static int[][] dxy = {{-1,0},{1,0},{0,-1},{0,1}};
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
N = Integer.parseInt(br.readLine());
answer = 0;
board = new int[N][N];
// ์
๋ ฅ ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
for(int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for(int j = 0; j < N; j++) {
board[i][j] = Integer.parseInt(st.nextToken());
}
}
// 3 ๋ฒ ์ ์๋ฅผ ์ธก์
for(int t=0; t < 4; t++) {
visited = new boolean[N][N];
marking = new Group[N][N];
// ๊ทธ๋ฃนํ ๋ฐ ๊ทธ๋ฃนํ ๊ฐ์ฒด๋ฅผ marking ๋ฐฐ์ด์ ์ ์ฅ
for(int i=0; i < N; i++) {
for(int j=0; j < N; j++) {
if(marking[i][j] != null) continue;
groupMethod(i,j, board[i][j]);
markGroup(i,j);
}
}
visited = new boolean[N][N];
// ๊ทธ๋ฃนํ ๋ ๊ทธ๋ฃน๋ค์ ๋ฐํ์ผ๋ก ๊ณ์ฐ ์ํ
for(int i=0; i < N; i++) {
for(int j=0; j < N; j++) {
if(visited[i][j]) continue;
groupAdjCnt = new HashMap<>(); // ๊ทธ๋ฃน ํ๋์ ๋ํด์ ๊ณ์ฐ์ ์ํํ ๋ ์ด๊ธฐํ
groupDfs(i, j, marking[i][j]);
calculateScore(i,j);
}
}
// ๋๋๋ฉด ํ๋ฒ์ฉ ํ์ ์ ์์ผ์ค์ผํจ.
board = rotate();
}
System.out.println(answer);
}
static void groupDfs(int i, int j, Group base) {
if(i < 0 || j < 0 || i >= N || j >= N || visited[i][j]) return;
if(marking[i][j] == base) {
visited[i][j] = true; // ํ์ฌ ํ์์ค์ธ ๊ทธ๋ฃน์ ๋ํด์๋ง -> ํด๋น ๊ทธ๋ฃน์ ๋ํ ๊ณ์ฐ์ ์ด๋ฒ์ ๋๋. 4๋ฐฉํฅ ํ์ํ
for(int d = 0; d < 4; d++) {
groupDfs(i+dxy[d][0], j+dxy[d][1], base);
}
}
else {
groupAdjCnt.put(marking[i][j], groupAdjCnt.getOrDefault(marking[i][j], 0) + 1);
return;
}
}
static void calculateScore(int x, int y) {
Group base = marking[x][y];
Set<Group> adjList = groupAdjCnt.keySet();
for(Group adjGroup : adjList) {
int score = (base.cnt + adjGroup.cnt) * base.number * adjGroup.number * groupAdjCnt.get(adjGroup);
if(score != 0) {
answer += score;
}
}
}
static int[][] rotate() {
int[][] rotated = new int[N][N];
// 1. ์ญ์๋ชจ์ ๋ฐ์๊ณ ํ์
// ์ญ์ ๊ฐ๋ก์ถ ๋ณต์ฌ (๊ธฐ์กด ์
๋ ฅ board ๊ธฐ์ค ํ์ )
for(int i=0; i<N; i++) {
rotated[(N-1) - i][N/2] = board[N/2][i];
}
// ์ญ์ ์ธ๋ก์ถ ๋ณต์ฌ (๊ธฐ์กด ์
๋ ฅ board ๊ธฐ์ค ํ์ )
for(int i=0; i<N; i++) {
rotated[N/2][i] = board[i][N/2];
}
// 2. ๊ฐ ๋ค ๊ตฌ์ญ ์๊ณ๋ฐฉํฅ ํ์
rotateQuarter(0, 0, rotated);
rotateQuarter(0, N/2+1, rotated);
rotateQuarter(N/2+1, 0, rotated);
rotateQuarter(N/2+1, N/2+1, rotated);
return rotated;
}
static void rotateQuarter(int x, int y, int[][] rotated){
// ๋ฐ๋ณต๋ฌธ์ iterator๋ฅผ ์ฆ๊ฐ ๊ฐ์ผ๋ก ์ฌ์ฉ ๊ธฐ๋ณธ x,y์ขํ๋ฅผ ๊ธฐ์ค
// ์์๋ฐ๋๋ ๊ฐ์ j๋ฅผ ํตํด ์กฐ์, ์ดํ ๋๋ฆฌ๊ฒ ๋ฐ๋๋๊ฐ์ i๋ฅผ ํตํด ์กฐ์
for(int i = 0; i < N/2; i++) {
for(int j = 0; j < N/2; j++) {
rotated[x+i][y+j] = board[x+(N/2-1)-j][y+i];
}
}
}
static void groupMethod(int i, int j, int num) {
if(i < 0 || j < 0 || i >= N || j >= N) return;
if(visited[i][j] || board[i][j] != num) return;
visited[i][j] = true;
for(int d = 0; d < 4; d++) {
groupMethod(i+dxy[d][0], j+dxy[d][1], num);
}
}
static void markGroup(int x, int y) {
int cnt = 0;
int num = board[x][y];
for(int i=0; i<N; i++) {
for(int j=0; j<N; j++) {
if(visited[i][j]) cnt++;
}
}
Group group = new Group(cnt, num);
for(int i=0; i<N; i++) {
for(int j=0; j<N; j++) {
if(visited[i][j]) {
marking[i][j] = group;
visited[i][j] = false;
}
}
}
}
}
ํ์ด
1. ๋ฉ์๋ ์ ๋ฆฌ
๋ฉ์๋ ๋ช | ์ญํ | ๋น๊ณ |
main | - ์
๋ ฅ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ - turn ๋ณ ๊ณผ์ ์งํ - simulation ๋ฉ์๋ ํธ์ถ |
|
void groupDfs(int i, int j, Group base) | - ์ธ์๋ก ๋์ด์จ i, j ๋ฅผ ๊ธฐ์ค์ผ๋ก ํด๋น ์ธ๋ฑ์ค๊ฐ ํฌํจ๋๋ ๊ทธ๋ฃน์ ๋ํด ์ธ์ ๊ทธ๋ฃน์ ์กฐ์ฌ - ๋ค๋ฅธ ์นธ์์ ์ด๋ฏธ ์กฐ์ฌํ์ ์ ์์ผ๋ฏ๋ก visited ์ฌ๋ถ ํ๋ณ ํ ์กฐ์ฌ ์์ - ์ธ์๋ก ๋์ด์จ base์ ๊ฐ์ ๊ฒฝ์ฐ์ ๊ฐ์ ๊ทธ๋ฃน์ด๋ฏ๋ก visited ์ฒ๋ฆฌ ๋ฐ ์ํ์ข์ฐ ๋ฐฉํฅ์ผ๋ก ์ด๋ - ์ธ์๋ก ๋์ด์จ base์ ๋ค๋ฅธ ๊ฒฝ์ฐ์ ์ธ์ ํ๊ทธ๋ฃน์ด๋ฏ๋ก HashMap ์ ์ ์ฅ -> getOrDefault ๋ฉ์๋๋ก ํค ์ถ๊ฐ ๋ฐ ๊ฐ ๋์ |
|
void calculateScore(int x, int y) | - ๋ฌธ์ ์์ ์ ์๋ ์ ์ ๊ณ์ฐ ๋ก์ง ๋ฐ์ | |
int[][] rotate() | - ์ญ์๋ชจ์ 90๋ ๋ฐ์๊ณ ํ์ - ๊ฐ ์ฌ๋ถ๋ฉด 90๋ ์๊ณ ํ์ - rotateQuarter๋ผ๋ ๋ณ๋์ ๋ฉ์๋ ์ถ๊ฐํด์ ์ฌ์ฉ |
|
void rotateQuarter(int x, int y, int[][] rotated) | - ๊ฐ ์ฌ๋ถ๋ฉด์ ๋ํ 90๋ ์๊ณ ํ์ ์งํ - ์ธ์๋ก ์์์ ์ขํ ๋ฐ rotated ๋ฐฐ์ด์ ๋ฐ์ ์ธ๋ฑ์ค ๊ณ์ฐํด์ ๋ฐ์ |
|
void groupMethod(int i, int j, int num) | - 2์ฐจ์ ๋ฐฐ์ด์ ํ์ํ๋ฉด์ ๊ฐ ๋ฒํธ๋ณ๋ก ๊ทธ๋ฃนํ์ ์งํํ๋ ๋ฉ์๋ - ํด๋น ๋ฉ์๋์์ visited๋ก ์ฒ๋ฆฌํด๋์ผ๋ฉด markGroup ๋ฉ์๋๋ฅผ ํตํด Group ๊ฐ์ฒด๋ฅผ ์ถ๊ฐํด marking ๋ฐฐ์ด์ ์ธ์คํด์ค ์ถ๊ฐ |
|
void markGroup(int x, int y) | - markGroup ๋ฉ์๋๋ groupMethod์์ visited์ฒ๋ฆฌ๋ฅผ ํด๋์ ์์ญ๋ค์ ๋ํด์ cnt ๊ฐ(๊ทธ๋ฃน์ ์ด๋ฃจ๋ ์นธ์ ์) ์ ์ธ๊ณ , ์ดํ Group ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด marking ๋ฐฐ์ด์ ์ ์ฅํ๋ค. - ์ฒ๋ฆฌ๊ฐ ๋๋๋ฉด visited ๊ฐ์ false๋ก ๋๋ ค๋๋๋ค. |
2. ์๋ฎฌ๋ ์ด์ ๋ฐ๋ณต ๋ก์ง ์ค๋ช
ํด๋น ๋ฌธ์ ์ ๊ฒฝ์ฐ ์๋์ ๊ฐ์ ์์๋ก 4๋ฒ for๋ฌธ์ ๋๋ ค ํ์ดํ์ต๋๋ค.
1. turn ๋ง๋ค ์ฌ์ฉํ visited ๋ฐฐ์ด ๋ฐ marking ๋ฐฐ์ด์ ์ด๊ธฐํ
2. ์ ๋ ฅ์ผ๋ก ๋ค์ด์จ ์ด๊ธฐ ๋ฐฐ์ด์์ ์ซ์๋ณ๋ก groupMethod๋ฅผ ํตํด ๊ทธ๋ฃนํ๋ฅผ ์ํค๊ณ ๊ฐ๊ฐ์ ๊ทธ๋ฃน์ ๋ํ์ฌ Group ๊ฐ์ฒด๋ฅผ ๋ฐฐ์ด์ ์ ์ฅํ๋ฉด์ ๋งํน by. markGroup (์ด๋ marking 2์ฐจ์ ๋ฐฐ์ด๋ด ๊ฐ ๊ทธ๋ฃน๋ณ ์์ญ์ ์ ์ฅ๋๋ Group๊ฐ์ฒด๋ ๋์ผ ์ฃผ์๊ฐ์ ๊ณต์ = ๊ฐ์ ๊ฐ์ฒด -> ์์๋ณต์ฌ)
3. ์ดํ visited ๋ฐฐ์ด์ ๋ค์ ์ด๊ธฐํํ๊ณ ๊ฐ ๊ทธ๋ฃน์ ๋๋ฉด์ ์ธ์ ํ ๋ณ์ ๊ฐ์๋ฅผ ๊ตฌํจ.
3.1. dfs๋ฅผ ํตํด ํ์ํ๋ฉด์ ํด๋น ๊ทธ๋ฃน์์ ๋ฐฉ๋ฌธํ ๊ณณ์ visited ์ฒ๋ฆฌ -> ๋ฐฉ๋ฌธํ ์๊ฐ ์ธ์ ํ ์นธ๋ค์ ๋ํด ๋ค๋ฅธ ๊ทธ๋ฃน์ธ์ง๋ฅผ ์ฒดํฌํ๊ณ ํด๋น ๊ทธ๋ฃน์ key ๊ฐ์ผ๋ก ๊ฐ์ง๋ HashMap<Group, Integer> groupAdjCnt ์ ์ซ์๋ฅผ ์ ์ฅ
3.2. ์ดํ ํด๋น ํด์ฌ๋งต์ ์ ์ฅ๋ ๊ฐ๋ค์ ์ด์ฉํด base ๊ทธ๋ฃน์ ๋ํด ์ธ์ ํ score๋ฅผ ๊ฒ์ฌ.
(**์ฐธ๊ณ ) ๋จ, visited ์ฒ๋ฆฌ๋ base ๊ทธ๋ฃน์ ๋ํด์๋ง ์งํํฉ๋๋ค. ์ดํ ๋ค๋ฅธ ๊ทธ๋ฃน์์๋ ์์ ์ธ์ ๊ทธ๋ฃน์ ์ฒดํฌํ group์ ๋ํด์๋ ์ ์๋ฅผ ์ธ์ง ์์๋ ๋๋ฏ๋ก -> ๋ฐฐ์ด์ ์ฐจ๊ทผ์ฐจ๊ทผ ์ฝ์ผ๋ฉฐ ๊ฑธ๋ฆฌ๋ group์ ๋ํด์ ์ธ์ ๋ฐฐ์ด์ ์ฒดํฌํ๋๋์ ์ดํ์๋ ๋ค์ ์ฒดํฌํ์ง ์๋๋ก ํจ.
4. ์ดํ turn์ ๋๊ธฐ๊ธฐ์ board ์ ๋ํด ๊ฐ์ด๋ฐ์ ๋ฐ์๊ณํ์ , ๊ฐ ์ฌ๋ถ๋ฉด ์๊ณ๋ฐฉํฅ 90๋ ํ์ ์ ์ ์ฉ(by. rotate())
3. ์ฃผ์ ๋ฉ์๋ ์ฝ๋ ์ค๋ช
3.1. groupDfs
static void groupDfs(int i, int j, Group base) {
if(i < 0 || j < 0 || i >= N || j >= N || visited[i][j]) return;
if(marking[i][j] == base) {
visited[i][j] = true; // ํ์ฌ ํ์์ค์ธ ๊ทธ๋ฃน์ ๋ํด์๋ง -> ํด๋น ๊ทธ๋ฃน์ ๋ํ ๊ณ์ฐ์ ์ด๋ฒ์ ๋๋. 4๋ฐฉํฅ ํ์ํ
for(int d = 0; d < 4; d++) {
groupDfs(i+dxy[d][0], j+dxy[d][1], base);
}
}
else {
groupAdjCnt.put(marking[i][j], groupAdjCnt.getOrDefault(marking[i][j], 0) + 1);
return;
}
}
- main ๋ฉ์๋์์ 2์ค for๋ฌธ์ ๋๋ฉฐ board์ ์ ์ฒด ๋ฐฐ์ด์ ํ์์ํจ๋ค.
- ํ์ํ๋ฉด์ ํด๋น ์์ญ์ด visited ์ฒ๋ฆฌ๊ฐ ๋์๋์ง ํ๋ณํ๊ณ ์ดํ ๋ฐฉ๋ฌธํ์ง ์์๋ค๋ฉด ๊ฒ์ฌํ์ง ์์ ๊ทธ๋ฃน์ผ๋ก ๋ถ๋ฅํด ํด๋น ์์ญ์ ๊ฒ์ฌํ๋ค.
- groupDfs ๋ฉ์๋๋ ๊ทธ๋ฐ ์ํฉ์์ ์ธ์๋ก ๋ค์ด์จ ์ขํ๊ฐ์ ํด๋นํ๋ ์์์ ๋ํด ๊ทธ๋ฃนํ ์์ผ ํด๋น ๊ทธ๋ฃน์ด ๊ฐ์ ๊ทธ๋ฃน์ธ์ง ํ๋ณํ๊ณ ์ดํ ๋ค๋ฅธ ๊ทธ๋ฃน์ ๋ํด์๋ ์ธ์ ํ๊ณ ์๋ค๊ณ ํ๋จํด์ groupAdjCnt (HashMap<Group, Integer>) ์ ๊ฐ์ ์ฌ๋ฆฐ๋ค.
- ์ด๋ Group์ key๊ฐ์ผ๋ก ์ฌ์ฉํ์ฌ base ๊ทธ๋ฃน์ ๋ํด ์ธ์ ํ Group์ ๋ณ์ ๊ฐ์ด ์ ์ฅ๋๊ฒ ๋๋ค.
- ์ด๋ฅผ ์ํด 2์ฐจ์ Group ํ์ ๋ฐฐ์ด marking์ ์ ์ธํด๋์๊ณ ํด๋น ์ขํ์ ์๋ Group๊ฐ์ฒด๋ฅผ marking ๋ฐฐ์ด๋ก ๋ถํฐ ์ป์ด์ ๋น๊ตํ ์ ์๋ค.
- getOrDefault ๋ฉ์๋๋ ์ค๋๋ง์ ์ฌ์ฉํด๋ดค๋๋ฐ ๋๋ฌด ์ค๋๋ง์ ์ฌ์ฉํด์ ๊ฑฐ์ ์ฒ์๋ณธ ๋ฉ์๋์ธ ๋๋์ด๋ค.
- ์ฒซ๋ฒ์งธ ์ธ์๋ก key๋ฅผ ์ ๋ ฅํ๊ณ ๋ ๋ฒ์งธ ์ธ์๋ก ์ด๊ธฐ๊ฐ์ ์ ๋ ฅํ๋ค.
- ๋ง์ผ ํด๋นํ๋ ํค๊ฐ์ด ์๋ค๋ฉด value๋ฅผ ๊ฐ์ ธ์ค๊ณ , ์๋ค๋ฉด ๋๋ฒ์งธ์ธ์์ธ 0์ ๊ฐ์ ธ์ค๊ฒ๋๋ค.
- ํด๋น ์ฌ์ฉ๋ฒ์ ์ ์์งํ๊ณ ์ฌ๋ฌ๋ชจ๋ก ์ ์ฌ์ฉํ ๊ฒ ๊ฐ์ ๋ฉ์๋์ด๋ค.
3.2. rotateQuarter
static void rotateQuarter(int x, int y, int[][] rotated){
// ๋ฐ๋ณต๋ฌธ์ iterator๋ฅผ ์ฆ๊ฐ ๊ฐ์ผ๋ก ์ฌ์ฉ ๊ธฐ๋ณธ x,y์ขํ๋ฅผ ๊ธฐ์ค
// ์์๋ฐ๋๋ ๊ฐ์ j๋ฅผ ํตํด ์กฐ์, ์ดํ ๋๋ฆฌ๊ฒ ๋ฐ๋๋๊ฐ์ i๋ฅผ ํตํด ์กฐ์
for(int i = 0; i < N/2; i++) {
for(int j = 0; j < N/2; j++) {
rotated[x+i][y+j] = board[x+(N/2-1)-j][y+i];
}
}
}
- ๊ฐ ์ฌ๋ถ๋ฉด(?) ์ด๋ผ๊ณ ํํํ๋๊ฒ ๋ง๋์ง ๋ชจ๋ฅด๋ ์๊ธด๊ฑด ์ฌ๋ถ๋ฉด์ด๋ค. ํด๋น ์์ญ๋ค์ ๋ํด์ ์๊ณ๋ฐฉํฅ 90๋ ๋ณํํ๋ ๋ฉ์๋์ด๋ค.
- ํด๋น ์ธ๋ฑ์ฑ์ ์ฝ๊ฒ ์ดํดํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ ๊ฐ์ for๋ฌธ์ ์์์ด ์ธ์๋ก๋ค์ด์จ x, y ๊ฐ ์๋๊ณ , ์์์ (์ข์ธก ์ต์๋จ ์ขํ)์ ๊ธฐ์ค์ผ๋ก ๊ฐ์ ์ฆ๊ฐ์ํค๋ ์ญํ ๋ก ์ฌ์ฉ๋๋ค๊ณ ์๊ฐํ๋ฉด ํ์ ๋ก์ง์ด ์ฝ๊ฒ ๋๊ปด์ง๋ค.