Skip to content
Merged
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
274 changes: 274 additions & 0 deletions Ho/202507/23.섬 지키키.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
```java
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class UserSolution
{
static int MAX_HASH_SIZE = 10000;
int N;
int[] hash;
Map<Integer, List<Block>> map;
int[][] temp;
boolean[][] vis;
int[][] grid;

public void init(int N, int mMap[][])
{
//init 과정에서 전처리가 필요함
map = new HashMap<>();
hash = new int[MAX_HASH_SIZE];
this.N = N;
grid = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
// 해당 블록을 기준으로 1 ~ 5개, 4방향 다 고려하기
// k가 현재 구조물 길이 결정
grid[i][j] = mMap[i][j];
for (int k = 1; k <= 4 ; k++) {

if(inRange(i, j + k)) {

int curHash = 0;

for (int l = 0; l < k; l++) {
curHash *= 10;
curHash += mMap[i][l + j] - mMap[i][l + 1 + j] + 5;
}

hash[curHash]++;
List<Block> list = map.getOrDefault(curHash, new ArrayList<>());
list.add(new Block(i, j, 0));
map.put(curHash, list);

int reverseHash = 0;
for (int l = k; l > 0; l--) {
reverseHash *= 10;
reverseHash += mMap[i][l + j] - mMap[i][l - 1 + j] + 5;
}

if (curHash != reverseHash) {
hash[reverseHash]++;
list = map.getOrDefault(reverseHash, new ArrayList<>());
list.add(new Block(i, j, 1));
map.put(reverseHash, list);
}
}

// 수직도 체크해야함
if(!inRange(i + k, j)) continue;

int verCurHash = 0;

for (int l = 0; l < k; l++) {
verCurHash *= 10;
verCurHash += mMap[l + i][j] - mMap[l + 1 + i][j] + 5;
}

hash[verCurHash]++;
List<Block> list = map.getOrDefault(verCurHash, new ArrayList<>());
list.add(new Block(i, j, 2));
map.put(verCurHash, list);

int verReverseHash = 0;
for (int l = k; l > 0; l--) {
verReverseHash *= 10;
verReverseHash += mMap[l + i][j] - mMap[l - 1 + i][j] + 5;
}


if(verCurHash != verReverseHash) {
hash[verReverseHash]++;
list = map.getOrDefault(verReverseHash, new ArrayList<>());
list.add(new Block(i, j, 3));
map.put(verReverseHash, list);
}
}

}
}
}

public int numberOfCandidate(int M, int mStructure[])
{
int sum = 0;
if(M == 1) {
return N * N;
}
int fHash = 0;

for (int i = 0; i < M - 1; i++) {
fHash *= 10;
fHash += mStructure[i+1] - mStructure[i] + 5;
}
sum += hash[fHash];
return sum;
}

public int maxArea(int M, int mStructure[], int mSeaLevel)
{
int hashNumber = 0;

for (int i = 0; i < M - 1; i++) {
hashNumber *= 10;
hashNumber += mStructure[i+1] - mStructure[i] + 5;
}

if(map.get(hashNumber) == null && M != 1) {
return -1;
}

if(M == 1) {
temp = new int[N][N];
int result = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
temp[i][j] += mStructure[0];
result = Math.max(bfs(mSeaLevel),result);
temp[i][j] -= mStructure[0];
}
}
return result;
}

List<Block> blocks = map.get(hashNumber);
// 상하좌우로만 영향을 주는 파도 bfs() 구현하기

int result = 0;


for(Block block : blocks) {
// 현재 블럭 위치에 구조물을 설치하고 섬 개수 카운팅
temp = new int[N][N];
if(block.dir == 0) {
for (int i = 0; i < M; i++) {
temp[block.r][block.c + i] = mStructure[i];
}
}
else if(block.dir == 1) {
for (int i = 0; i < M; i++) {
temp[block.r][block.c + M - 1 - i] = mStructure[i];
}
}
else if(block.dir == 2) {
for (int i = 0; i < M; i++) {
temp[block.r + i][block.c] = mStructure[i];
}
}
else if(block.dir == 3) {
for (int i = 0; i < M; i++) {
temp[block.r + M - 1 - i][block.c] = mStructure[i];
}
}

int cnt = bfs(mSeaLevel);
result = Math.max(result, cnt);
}

return result;
}

int[] drs = {0, 0, 1, -1};
int[] dcs = {1, -1, 0, 0};

private int bfs(int mSeaLevel) {
vis = new boolean[N][N];

ArrayDeque<Pair> q = new ArrayDeque<>();
for (int i = 0; i < N; i++) {
if (canGo(0, i, mSeaLevel)) {
vis[0][i] = true;
q.add(new Pair(0, i));
}
if (canGo(i, 0, mSeaLevel)) {
vis[i][0] = true;
q.add(new Pair(i, 0));
}
if(canGo(N-1,i, mSeaLevel)) {
vis[N-1][i] = true;
q.add(new Pair(N-1, i));
}
if(canGo(i, N-1, mSeaLevel)) {
vis[i][N-1] = true;
q.add(new Pair(i, N-1));
}
}

while(!q.isEmpty()) {
Pair cur = q.poll();

for (int i = 0; i < 4; i++) {
int nr = cur.r + drs[i];
int nc = cur.c + dcs[i];

if(canGo(nr, nc, mSeaLevel)) {
vis[nr][nc] = true;
q.add(new Pair(nr, nc));
}
}
}

int cnt = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if(!vis[i][j]) {
cnt++;
}
}
}
return cnt;
}

private boolean canGo(int r, int c, int mSeaLevel) {
if(!inRange(r, c)) return false;
if(vis[r][c]) return false;
if(grid[r][c] + temp[r][c] >= mSeaLevel) return false;
return true;
}

private boolean inRange(int r, int c) {
return r >= 0 && r < N && c >= 0 && c < N;
}

class Block {
// dir 0: 우, 1 리버스, 2 하, 3,하 리버스
int r, c, dir;

public Block(int r, int c,int dir) {
this.r = r;
this.c = c;
this.dir = dir;
}
}

class Pair {
int r, c;

public Pair(int r, int c) {
this.r = r;
this.c = c;
}
}
/**
* 정방향
* 90도만 돌리기
* 리버스 돌리기
* 90도 + 리버스 돌리기
*/

/**
* 발생할 수 있는 모든 경우의 수를 cache에 저장하기
* 1개인 경우는 고려안해도 된다.
*
* i 에서 i + 1 번쨰의 차를 구하고 + 5한 값을 사용한다.
*
*/

/**
* 부족했던 부분
* 각 타일간 gap을 이용해서 해싱하는 부분을 잘 못한다.
*/
}
```