1번
문제 링크
- 문제의 입력이 충분히 짧기 때문에 직관적으로 있는 그대로 풀어도 상관이 없다.
- 조건에 맞추어 문제에 맞게 코드를 구현하면 된다.
function solution(bandage, health, attacks) {
let [t, x, y] = bandage;
let currentTime = 0;
let currentHealth = health;
let maxHealth = health;
let continuousHealTime = 0;
while (attacks.length && currentHealth > 0) {
const [attackTime, attackDamage] = attacks[0];
if (currentTime < attackTime) {
currentHealth += x;
continuousHealTime++;
if(continuousHealTime >= t) {
currentHealth += y;
continuousHealTime = 0;
}
if (currentHealth > maxHealth) currentHealth = maxHealth;
}
else {
attacks.shift();
currentHealth -= attackDamage;
continuousHealTime = 0;
}
currentTime++;
}
return currentHealth > 0 ? currentHealth : -1;
}
2번
문제 링크
- bfs를 통해 석유의 좌표와 양을 확인해 가장 많이 석유를 뽑을 수 있는 구역을 찾으면 된다.
- bfs 함수에서 각 덩어리별로 Set으로 석유를 캐낼 수 있는 좌표를, 정수로 석유의 양을 전달해준다.
- 각 위치별로 얼마나 석유를 캘 수 있는지 구해 최대값을 구하면 된다.
- 아래 코드대로는 시간제한에 걸린다. bfs함수에서 방문할 점을 미리 걸러내야 시간초과없이 문제를 해결할 수 있다.
function solution(land) {
let totalOilArray = new Array(land[0].length).fill(0);
const isVisited = Array.from({length: land.length}, () => new Array(land[0].length).fill(0));
const bfs = (coordX, coordY) => {
const includesSet = new Set();
let oilSize = 0;
const visitArray = [[coordX, coordY]];
for (let i = 0; i < visitArray.length; i++) {
const [currentX, currentY] = visitArray[i];
if (isVisited[currentX][currentY] === 1) continue;
else {
isVisited[currentX][currentY] = 1;
includesSet.add(currentY);
oilSize++;
if (currentX > 0);
if (currentY > 0);
if (currentX < land.length - 1);
if (currentY < land[0].length - 1);
}
}
return {set: includesSet, size: oilSize};
}
for(let i = 0; i < land.length; i++) {
for(let j = 0; j < land[0].length; j++) {
if(land[i][j] === 1 && isVisited[i][j] === 0) {
const {set, size} = bfs(i, j);
set.forEach(target => totalOilArray[target] += size);
}
else isVisited[i][j] = 1;
}
}
return Math.max(...totalOilArray);
}
3번
문제 링크
- 분침과는 1분에 1회이상, 초침과는 1시간에 1회 이상 만날 수 없다.
- 그런데 주어진 시간은 초단위로 주어진다. 1초에 1회이상 만날수 없다는 사실만 기억하자
- 하루종일 1초단위로 겹치는지 확인해도 84000번밖에 안된다.
- 시계의 각도를 계산한 다음 1초마다 시침, 분침이 겹치는지 확인해주고, 마지막 시간, 12/24시 정각의 경우만 따로 예외처리를 해주면 된다.
function solution(h1, m1, s1, h2, m2, s2) {
const hourRadFirst = ((h1 * 60 * 60) + (m1 * 60) + s1);
const hourRadLast = ((h2 * 60 * 60) + (m2 * 60) + s2);
let hourRad = (((h1 % 12) * 60 * 60) + (m1 * 60) + s1);
let minRad = ((m1 * 60) + s1) * 12;
let secRad = s1 * 720;
let answer = 0;
for (let i = 0; i < hourRadLast - hourRadFirst; i++) {
if (hourRad >= secRad && hourRad + 1 < secRad + 720) answer++;
if (minRad >= secRad && minRad + 12 < secRad + 720) answer++;
hourRad = (hourRad + 1) % 43200
minRad = (minRad + 12) % 43200
secRad = (secRad + 720) % 43200
}
if (hourRad === secRad) answer++;
if (minRad === secRad) answer++;
if (hourRadFirst === 0) answer--;
if (hourRadFirst <= 43200 && hourRadLast >= 43200) answer--;
return answer;
}
4번
문제 링크
- 문제 자체는 완전탐색 문제이나, 수레를 동시에 2개씩 옮겨야 한다는 특징이 있다.
- dfs, bfs 어느 방법으로도 풀 수 있으나, 재귀의 깊이가 깊어야 32이기 때문에 dfs방식을 택했다.
- dfs 함수에는 현재 각각의 수레위치, 중복 방문 확인을 위한 지금 점 직전까지의 수레가 움직인 기록이 필요하다.
- dfs 탐색시 움직인 기록이 모순이 되는 경우는 아래와 같다.
- 벽으로 움직인 경우
- 두 수레가 겹치는 경우
- 각 수레가 이전에 방문한 적이 있는 경우
- 모순이 없다면 빨간색, 파란색 수레 중 하나를 움직여야 한다
- 처음에는 빨간색, 파란색 양쪽을 다 움직여봐야 한다. (아닐시 테케에서 걸림)
- 빨간색, 파란색 어느 한쪽이 이동이 완료되었다면, 나머지 한 색상의 수레만 움직일 수 있다.
- 이동이 둘다 완료되지 않았으면 직전에 움직인 색상과 반대되는 색상의 수레를 움직여주면 된다.
- 두 수레가 모두 도착했으면 지금까지 이동한 경로를 배열에 push해준다.
- 경로들 중 가장 최단거리를 구하면 된다.
function solution(maze) {
let redStartCoord;
let blueStartCoord;
let redCompleteCoord;
let blueCompleteCoord;
for (let i = 0; i < maze.length; i++) {
for (let j = 0; j < maze[0].length; j++) {
if (maze[i][j] === 0 || maze[i][j] === 5) continue;
if (maze[i][j] === 1) redStartCoord = [i, j];
if (maze[i][j] === 2) blueStartCoord = [i, j];
if (maze[i][j] === 3) redCompleteCoord = [i, j];
if (maze[i][j] === 4) blueCompleteCoord = [i, j];
maze[i][j] = 0;
}
}
const rootArray = [];
const dfs = (redCoord, blueCoord, visitArray) => {
const isRedComplete = redCoord[0] === redCompleteCoord[0] && redCoord[1] === redCompleteCoord[1];
const isBlueComplete = blueCoord[0] === blueCompleteCoord[0] && blueCoord[1] === blueCompleteCoord[1];
if (maze[redCoord[0]][redCoord[1]] === 5) return;
if (maze[blueCoord[0]][blueCoord[1]] === 5) return;
if (redCoord[0] === blueCoord[0] && redCoord[1] === blueCoord[1]) return;
if (visitArray.some(([x, y, color]) => x === redCoord[0] && y === redCoord[1] && color === "red")) return;
if (visitArray.some(([x, y, color]) => x === blueCoord[0] && y === blueCoord[1] && color === "blue")) return;
if (isRedComplete === true && isBlueComplete === true) {
rootArray.push(visitArray);
return;
}
const redMove = () => {
const [redX, redY] = redCoord;
if (redX > 0) dfs([redX - 1, redY], [...blueCoord], [...visitArray, [redX, redY, "red"]]);
if (redY > 0) dfs([redX, redY - 1], [...blueCoord], [...visitArray, [redX, redY, "red"]]);
if (redX < maze.length - 1) dfs([redX + 1, redY], [...blueCoord], [...visitArray, [redX, redY, "red"]]);
if (redY < maze[0].length - 1) dfs([redX, redY + 1], [...blueCoord], [...visitArray, [redX, redY, "red"]]);
}
const blueMove = () => {
const [blueX, blueY] = blueCoord;
if (blueX > 0) dfs([...redCoord], [blueX - 1, blueY], [...visitArray, [blueX, blueY, "blue"]]);
if (blueY > 0) dfs([...redCoord], [blueX, blueY - 1], [...visitArray, [blueX, blueY, "blue"]]);
if (blueX < maze.length - 1) dfs([...redCoord], [blueX + 1, blueY], [...visitArray, [blueX, blueY, "blue"]]);
if (blueY < maze[0].length - 1) dfs([...redCoord], [blueX, blueY + 1], [...visitArray, [blueX, blueY, "blue"]]);
}
if (visitArray.length === 0) {
redMove();
blueMove();
}
else if (isBlueComplete === true || (isRedComplete === false && isBlueComplete === false && visitArray[visitArray.length - 1][2] === "blue")) redMove();
else blueMove();
}
dfs(redStartCoord, blueStartCoord, []);
const answerArray = rootArray.map(root => {
const redNum = root.filter(([x, y, result]) => result === "red").length;
const blueNum = root.length - redNum;
return Math.max(redNum, blueNum);
});
return answerArray.length === 0 ? 0 : Math.min(...answerArray)
}