728x90
반응형
스택 구현 예제
public static void main(String[] args) {
Stack<Integer> s = new Stack<>();
// 삽입(5) - 삽입(2) - 삽입(3) - 삽입(7) - 삭제() - 삽입(1) - 삽입(4) - 삭제()
s.push(5);
s.push(2);
s.push(3);
s.push(7);
s.pop();
s.push(1);
s.push(4);
s.pop();
// 스택의 최상단 원소부터 출력
while (!s.empty()) {
System.out.println(s.peek());
s.pop();
}
}
큐 구현 예제
public static void main(String[] args) {
Queue<Integer> q = new LinkedList<>();
// 삽입(5) - 삽입(2) - 삽입(3) - 삽입(7) - 삭제() - 삽입(1) - 삽입(4) - 삭제()
q.offer(5);
q.offer(2);
q.offer(3);
q.offer(7);
q.poll();
q.offer(1);
q.offer(4);
q.poll();
// 먼저 들어온 원소부터 추출
while (!q.isEmpty()) {
System.out.println(q.poll());
}
}
무한히 반복되는 재귀함수 예제
public static void recursiveFunction() {
System.out.println("재귀 함수를 호출합니다.");
recursiveFunction();
}
public static void main(String[] args) {
recursiveFunction();
}
재귀함수의 종료 조건 예제
public static void recursiveFunction(int i) {
// 100번째 호출을 했을 때 종료되도록 종료 조건 명시
if (i == 100) return;
System.out.println(i + "번째 재귀 함수에서 " + (i + 1) + "번째 재귀함수를 호출합니다.");
recursiveFunction(i + 1);
System.out.println(i + "번째 재귀 함수를 종료합니다.");
}
public static void main(String[] args) {
recursiveFunction(1);
}
2가지 방식으로 구현한 팩토리얼 예제
// 반복적으로 구현한 n!
public static int factorialIterative(int n) {
int result = 1;
// 1부터 n까지의 수를 차례대로 곱하기
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
// 재귀적으로 구현한 n!
public static int factorialRecursive(int n) {
// n이 1 이하인 경우 1을 반환
if (n <= 1) return 1;
// n! = n * (n - 1)!를 그대로 코드로 작성하기
return n * factorialRecursive(n - 1);
}
public static void main(String[] args) {
// 각각의 방식으로 구현한 n! 출력(n = 5)
System.out.println("반복적으로 구현:" + factorialIterative(5));
System.out.println("재귀적으로 구현:" + factorialRecursive(5));
}
인접 행렬 예제
public static final int INF = 999999999;
// 2차원 리스트를 이용해 인접 행렬 표현
public static int[][] graph = {
{0, 7, 5},
{7, 0, INF},
{5, INF, 0}
};
public static void main(String[] args) {
// 그래프 출력
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(graph[i][j] + " ");
}
System.out.println();
}
}
인접 리스트 예제
class Node {
private int index;
private int distance;
public Node(int index, int distance) {
this.index = index;
this.distance = distance;
}
public void show() {
System.out.print("(" + this.index + "," + this.distance + ") ");
}
}
public class Main {
// 행(Row)이 3개인 인접 리스트 표현
public static ArrayList<ArrayList<Node>> graph = new ArrayList<ArrayList<Node>>();
public static void main(String[] args) {
// 그래프 초기화
for (int i = 0; i < 3; i++) {
graph.add(new ArrayList<Node>());
}
// 노드 0에 연결된 노드 정보 저장 (노드, 거리)
graph.get(0).add(new Node(1, 7));
graph.get(0).add(new Node(2, 5));
// 노드 1에 연결된 노드 정보 저장 (노드, 거리)
graph.get(1).add(new Node(0, 7));
// 노드 2에 연결된 노드 정보 저장 (노드, 거리)
graph.get(2).add(new Node(0, 5));
// 그래프 출력
for (int i = 0; i < 3; i++) {
for (int j = 0; j < graph.get(i).size(); j++) {
graph.get(i).get(j).show();
}
System.out.println();
}
}
}
DFS
public class Main {
public static boolean[] visited = new boolean[9];
public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
// DFS 함수 정의
public static void dfs(int x) {
// 현재 노드를 방문 처리
visited[x] = true;
System.out.print(x + " ");
// 현재 노드와 연결된 다른 노드를 재귀적으로 방문
for (int i = 0; i < graph.get(x).size(); i++) {
int y = graph.get(x).get(i);
if (!visited[y]) dfs(y);
}
}
public static void main(String[] args) {
// 그래프 초기화
for (int i = 0; i < 9; i++) {
graph.add(new ArrayList<Integer>());
}
// 노드 1에 연결된 노드 정보 저장
graph.get(1).add(2);
graph.get(1).add(3);
graph.get(1).add(8);
// 노드 2에 연결된 노드 정보 저장
graph.get(2).add(1);
graph.get(2).add(7);
// 노드 3에 연결된 노드 정보 저장
graph.get(3).add(1);
graph.get(3).add(4);
graph.get(3).add(5);
// 노드 4에 연결된 노드 정보 저장
graph.get(4).add(3);
graph.get(4).add(5);
// 노드 5에 연결된 노드 정보 저장
graph.get(5).add(3);
graph.get(5).add(4);
// 노드 6에 연결된 노드 정보 저장
graph.get(6).add(7);
// 노드 7에 연결된 노드 정보 저장
graph.get(7).add(2);
graph.get(7).add(6);
graph.get(7).add(8);
// 노드 8에 연결된 노드 정보 저장
graph.get(8).add(1);
graph.get(8).add(7);
dfs(1);
}
}
BFS
public class Main {
public static boolean[] visited = new boolean[9];
public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
// BFS 함수 정의
public static void bfs(int start) {
Queue<Integer> q = new LinkedList<>();
q.offer(start);
// 현재 노드를 방문 처리
visited[start] = true;
// 큐가 빌 때까지 반복
while(!q.isEmpty()) {
// 큐에서 하나의 원소를 뽑아 출력
int x = q.poll();
System.out.print(x + " ");
// 해당 원소와 연결된, 아직 방문하지 않은 원소들을 큐에 삽입
for(int i = 0; i < graph.get(x).size(); i++) {
int y = graph.get(x).get(i);
if(!visited[y]) {
q.offer(y);
visited[y] = true;
}
}
}
}
public static void main(String[] args) {
// 그래프 초기화
for (int i = 0; i < 9; i++) {
graph.add(new ArrayList<Integer>());
}
// 노드 1에 연결된 노드 정보 저장
graph.get(1).add(2);
graph.get(1).add(3);
graph.get(1).add(8);
// 노드 2에 연결된 노드 정보 저장
graph.get(2).add(1);
graph.get(2).add(7);
// 노드 3에 연결된 노드 정보 저장
graph.get(3).add(1);
graph.get(3).add(4);
graph.get(3).add(5);
// 노드 4에 연결된 노드 정보 저장
graph.get(4).add(3);
graph.get(4).add(5);
// 노드 5에 연결된 노드 정보 저장
graph.get(5).add(3);
graph.get(5).add(4);
// 노드 6에 연결된 노드 정보 저장
graph.get(6).add(7);
// 노드 7에 연결된 노드 정보 저장
graph.get(7).add(2);
graph.get(7).add(6);
graph.get(7).add(8);
// 노드 8에 연결된 노드 정보 저장
graph.get(8).add(1);
graph.get(8).add(7);
bfs(1);
}
}
음료수 얼려 먹기(CCL)
public class Main {
public static int n, m;
public static int[][] graph = new int[1000][1000];
// DFS로 특정 노드를 방문하고 연결된 모든 노드들도 방문
public static boolean dfs(int x, int y) {
// 주어진 범위를 벗어나는 경우에는 즉시 종료
if (x <= -1 || x >=n || y <= -1 || y >= m) {
return false;
}
// 현재 노드를 아직 방문하지 않았다면
if (graph[x][y] == 0) {
// 해당 노드 방문 처리
graph[x][y] = 1;
// 상, 하, 좌, 우의 위치들도 모두 재귀적으로 호출
dfs(x - 1, y);
dfs(x, y - 1);
dfs(x + 1, y);
dfs(x, y + 1);
return true;
}
return false;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// N, M을 공백을 기준으로 구분하여 입력 받기
n = sc.nextInt();
m = sc.nextInt();
sc.nextLine(); // 버퍼 지우기
// 2차원 리스트의 맵 정보 입력 받기
for (int i = 0; i < n; i++) {
String str = sc.nextLine();
for (int j = 0; j < m; j++) {
graph[i][j] = str.charAt(j) - '0';
}
}
// 모든 노드(위치)에 대하여 음료수 채우기
int result = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
// 현재 위치에서 DFS 수행
if (dfs(i, j)) {
result += 1;
}
}
}
System.out.println(result); // 정답 출력
}
}
미로 탈출
class Node {
private int x;
private int y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
}
public class Main {
public static int n, m;
public static int[][] graph = new int[201][201];
// 이동할 네 가지 방향 정의 (상, 하, 좌, 우)
public static int dx[] = {-1, 1, 0, 0};
public static int dy[] = {0, 0, -1, 1};
public static int bfs(int x, int y) {
// 큐(Queue) 구현을 위해 queue 라이브러리 사용
Queue<Node> q = new LinkedList<>();
q.offer(new Node(x, y));
// 큐가 빌 때까지 반복하기
while(!q.isEmpty()) {
Node node = q.poll();
x = node.getX();
y = node.getY();
// 현재 위치에서 4가지 방향으로의 위치 확인
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
// 미로 찾기 공간을 벗어난 경우 무시
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
// 벽인 경우 무시
if (graph[nx][ny] == 0) continue;
// 해당 노드를 처음 방문하는 경우에만 최단 거리 기록
if (graph[nx][ny] == 1) {
graph[nx][ny] = graph[x][y] + 1;
q.offer(new Node(nx, ny));
}
}
}
// 가장 오른쪽 아래까지의 최단 거리 반환
return graph[n - 1][m - 1];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// N, M을 공백을 기준으로 구분하여 입력 받기
n = sc.nextInt();
m = sc.nextInt();
sc.nextLine(); // 버퍼 지우기
// 2차원 리스트의 맵 정보 입력 받기
for (int i = 0; i < n; i++) {
String str = sc.nextLine();
for (int j = 0; j < m; j++) {
graph[i][j] = str.charAt(j) - '0';
}
}
// BFS를 수행한 결과 출력
System.out.println(bfs(0, 0));
}
}
특정 거리의 도시 찾기 (핵심 유형)
public class Main {
// 도시의 개수, 도로의 개수, 거리 정보, 출발 도시 번호
public static int n, m, k, x;
public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
// 모든 도시에 대한 최단 거리 초기화
public static int[] d = new int[300001];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
k = sc.nextInt();
x = sc.nextInt();
// 그래피 및 최단 거리 테이블 초기화
for (int i = 0; i <= n; i++) {
graph.add(new ArrayList<Integer>());
d[i] = -1;
}
// 모든 도로 정보 입력 받기
for (int i = 0; i < m; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
graph.get(a).add(b);
}
// 출발 도시까지의 거리는 0으로 설정
d[x] = 0;
// 너비 우선 탐색(BFS) 수행
Queue<Integer> q = new LinkedList<Integer>();
q.offer(x);
while (!q.isEmpty()) {
int now = q.poll();
// 현재 도시에서 이동할 수 있는 모든 도시를 확인
for (int i = 0; i < graph.get(now).size(); i++) {
int nextNode = graph.get(now).get(i);
// 아직 방문하지 않은 도시라면
if (d[nextNode] == -1) {
// 최단 거리 갱신
d[nextNode] = d[now] + 1;
q.offer(nextNode);
}
}
}
// 최단 거리가 K인 모든 도시의 번호를 오름차순으로 출력
boolean check = false;
for (int i = 1; i <= n; i++) {
if (d[i] == k) {
System.out.println(i);
check = true;
}
}
// 만약 최단 거리가 K인 도시가 없다면, -1 출력
if (!check) System.out.println(-1);
}
}
연구소 (삼성)
public class Main {
public static int n, m, result = 0;
public static int[][] arr = new int[8][8]; // 초기 맵 배열
public static int[][] temp = new int[8][8]; // 벽을 설치한 뒤의 맵 배열
// 4가지 이동 방향에 대한 배열
public static int[] dx = {-1, 0, 1, 0};
public static int[] dy = {0, 1, 0, -1};
// 깊이 우선 탐색(DFS)을 이용해 각 바이러스가 사방으로 퍼지도록 하기
public static void virus(int x, int y) {
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
// 상, 하, 좌, 우 중에서 바이러스가 퍼질 수 있는 경우
if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
if (temp[nx][ny] == 0) {
// 해당 위치에 바이러스 배치하고, 다시 재귀적으로 수행
temp[nx][ny] = 2;
virus(nx, ny);
}
}
}
}
// 현재 맵에서 안전 영역의 크기 계산하는 메서드
public static int getScore() {
int score = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (temp[i][j] == 0) {
score += 1;
}
}
}
return score;
}
// 깊이 우선 탐색(DFS)을 이용해 울타리를 설치하면서, 매 번 안전 영역의 크기 계산
public static void dfs(int count) {
// 울타리가 3개 설치된 경우
if (count == 3) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
temp[i][j] = arr[i][j];
}
}
// 각 바이러스의 위치에서 전파 진행
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (temp[i][j] == 2) {
virus(i, j);
}
}
}
// 안전 영역의 최대값 계산
result = Math.max(result, getScore());
return;
}
// 빈 공간에 울타리를 설치
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (arr[i][j] == 0) {
arr[i][j] = 1;
count += 1;
dfs(count);
arr[i][j] = 0;
count -= 1;
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
arr[i][j] = sc.nextInt();
}
}
dfs(0);
System.out.println(result);
}
}
경쟁적 전염 (핵심 유형)
class Virus implements Comparable<Virus> {
private int index;
private int second;
private int x;
private int y;
public Virus(int index, int second, int x, int y) {
this.index = index;
this.second = second;
this.x = x;
this.y = y;
}
public int getIndex() {
return this.index;
}
public int getSecond() {
return this.second;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
// 정렬 기준은 '번호가 낮은 순서'
@Override
public int compareTo(Virus other) {
if (this.index < other.index) {
return -1;
}
return 1;
}
}
public class Main {
public static int n, k;
// 전체 보드 정보를 담는 배열
public static int[][] graph = new int[200][200];
public static ArrayList<Virus> viruses = new ArrayList<Virus>();
// 바이러스가 퍼져나갈 수 있는 4가지의 위치
public static int[] dx = {-1, 0, 1, 0};
public static int[] dy = {0, 1, 0, -1};
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
k = sc.nextInt();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
graph[i][j] = sc.nextInt();
// 해당 위치에 바이러스가 존재하는 경우
if (graph[i][j] != 0) {
// (바이러스 종류, 시간, 위치 X, 위치 Y) 삽입
viruses.add(new Virus(graph[i][j], 0, i, j));
}
}
}
// 정렬 이후에 큐로 옮기기 (낮은 번호의 바이러스가 먼저 증식하므로)
Collections.sort(viruses);
Queue<Virus> q = new LinkedList<Virus>();
for (int i = 0; i < viruses.size(); i++) {
q.offer(viruses.get(i));
}
int targetS = sc.nextInt();
int targetX = sc.nextInt();
int targetY = sc.nextInt();
// 너비 우선 탐색(BFS) 진행
while (!q.isEmpty()) {
Virus virus = q.poll();
// 정확히 second만큼 초가 지나거나, 큐가 빌 때까지 반복
if (virus.getSecond() == targetS) break;
// 현재 노드에서 주변 4가지 위치를 각각 확인
for (int i = 0; i < 4; i++) {
int nx = virus.getX() + dx[i];
int ny = virus.getY() + dy[i];
// 해당 위치로 이동할 수 있는 경우
if (0 <= nx && nx < n && 0 <= ny && ny < n) {
// 아직 방문하지 않은 위치라면, 그 위치에 바이러스 넣기
if (graph[nx][ny] == 0) {
graph[nx][ny] = virus.getIndex();
q.offer(new Virus(virus.getIndex(), virus.getSecond() + 1, nx, ny));
}
}
}
}
System.out.println(graph[targetX - 1][targetY - 1]);
}
}
괄호 변환 (카카오)
class Solution {
// "균형잡힌 괄호 문자열"의 인덱스 반환
public int balancedIndex(String p) {
int count = 0; // 왼쪽 괄호의 개수
for (int i = 0; i < p.length(); i++) {
if (p.charAt(i) == '(') count += 1;
else count -= 1;
if (count == 0) return i;
}
return -1;
}
// "올바른 괄호 문자열"인지 판단
public boolean checkProper(String p) {
int count = 0; // 왼쪽 괄호의 개수
for (int i = 0; i < p.length(); i++) {
if (p.charAt(i) == '(') count += 1;
else {
if (count == 0) { // 쌍이 맞지 않는 경우에 false 반환
return false;
}
count -= 1;
}
}
return true; // 쌍이 맞는 경우에 true 반환
}
public String solution(String p) {
String answer = "";
if (p.equals("")) return answer;
int index = balancedIndex(p);
String u = p.substring(0, index + 1);
String v = p.substring(index + 1);
// "올바른 괄호 문자열"이면, v에 대해 함수를 수행한 결과를 붙여 반환
if (checkProper(u)) {
answer = u + solution(v);
}
// "올바른 괄호 문자열"이 아니라면 아래의 과정을 수행
else {
answer = "(";
answer += solution(v);
answer += ")";
u = u.substring(1, u.length() - 1); // 첫 번째와 마지막 문자를 제거
String temp = "";
for (int i = 0; i < u.length(); i++) {
if (u.charAt(i) == '(') temp += ")";
else temp += "(";
}
answer += temp;
}
return answer;
}
}
연산자 끼워 넣기 (삼성)
public class Main {
public static int n;
// 연산을 수행하고자 하는 수 리스트
public static ArrayList<Integer> arr = new ArrayList<>();
// 더하기, 빼기, 곱하기, 나누기 연산자 개수
public static int add, sub, mul, divi;
// 최솟값과 최댓값 초기화
public static int minValue = (int) 1e9;
public static int maxValue = (int) -1e9;
// 깊이 우선 탐색 (DFS) 메서드
public static void dfs(int i, int now) {
// 모든 연산자를 다 사용한 경우, 최솟값과 최댓값 업데이트
if (i == n) {
minValue = Math.min(minValue, now);
maxValue = Math.max(maxValue, now);
}
else {
// 각 연산자에 대하여 재귀적으로 수행
if (add > 0) {
add -= 1;
dfs(i + 1, now + arr.get(i));
add += 1;
}
if (sub > 0) {
sub -= 1;
dfs(i + 1, now - arr.get(i));
sub += 1;
}
if (mul > 0) {
mul -= 1;
dfs(i + 1, now * arr.get(i));
mul += 1;
}
if (divi > 0) {
divi -= 1;
dfs(i + 1, now / arr.get(i));
divi += 1;
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i = 0; i < n; i++) {
int x = sc.nextInt();
arr.add(x);
}
add = sc.nextInt();
sub = sc.nextInt();
mul = sc.nextInt();
divi = sc.nextInt();
// DFS 메서드 호출
dfs(1, arr.get(0));
// 최댓값과 최솟값 차례대로 출력
System.out.println(maxValue);
System.out.println(minValue);
}
}
감시 피하기 (핵심 유형)
class Combination {
private int n;
private int r;
private int[] now; // 현재 조합
private ArrayList<ArrayList<Position>> result; // 모든 조합
public ArrayList<ArrayList<Position>> getResult() {
return result;
}
public Combination(int n, int r) {
this.n = n;
this.r = r;
this.now = new int[r];
this.result = new ArrayList<ArrayList<Position>>();
}
public void combination(ArrayList<Position> arr, int depth, int index, int target) {
if (depth == r) {
ArrayList<Position> temp = new ArrayList<>();
for (int i = 0; i < now.length; i++) {
temp.add(arr.get(now[i]));
}
result.add(temp);
return;
}
if (target == n) return;
now[index] = target;
combination(arr, depth + 1, index + 1, target + 1);
combination(arr, depth, index, target + 1);
}
}
class Position {
private int x;
private int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
}
public class Main {
public static int n; // 복도의 크기
public static char[][] board = new char[6][6]; // 복도 정보 (N x N)
public static ArrayList<Position> teachers = new ArrayList<>(); // 모든 선생님 위치 정보
public static ArrayList<Position> spaces = new ArrayList<>(); // 모든 빈 공간 위치 정보
// 특정 방향으로 감시를 진행 (학생 발견: true, 학생 미발견: false)
public static boolean watch(int x, int y, int direction) {
// 왼쪽 방향으로 감시
if (direction == 0) {
while (y >= 0) {
if (board[x][y] == 'S') { // 학생이 있는 경우
return true;
}
if (board[x][y] == 'O') { // 장애물이 있는 경우
return false;
}
y -= 1;
}
}
// 오른쪽 방향으로 감시
if (direction == 1) {
while (y < n) {
if (board[x][y] == 'S') { // 학생이 있는 경우
return true;
}
if (board[x][y] == 'O') { // 장애물이 있는 경우
return false;
}
y += 1;
}
}
// 위쪽 방향으로 감시
if (direction == 2) {
while (x >= 0) {
if (board[x][y] == 'S') { // 학생이 있는 경우
return true;
}
if (board[x][y] == 'O') { // 장애물이 있는 경우
return false;
}
x -= 1;
}
}
// 아래쪽 방향으로 감시
if (direction == 3) {
while (x < n) {
if (board[x][y] == 'S') { // 학생이 있는 경우
return true;
}
if (board[x][y] == 'O') { // 장애물이 있는 경우
return false;
}
x += 1;
}
}
return false;
}
// 장애물 설치 이후에, 한 명이라도 학생이 감지되는지 검사
public static boolean process() {
// 모든 선생의 위치를 하나씩 확인
for (int i = 0; i < teachers.size(); i++) {
int x = teachers.get(i).getX();
int y = teachers.get(i).getY();
// 4가지 방향으로 학생을 감지할 수 있는지 확인
for (int j = 0; j < 4; j++) {
if (watch(x, y, j)) {
return true;
}
}
}
return false;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
board[i][j] = sc.next().charAt(0);
// 선생님이 존재하는 위치 저장
if (board[i][j] == 'T') {
teachers.add(new Position(i, j));
}
// 장애물을 설치할 수 있는 (빈 공간) 위치 저장
if (board[i][j] == 'X') {
spaces.add(new Position(i, j));
}
}
}
// 빈 공간에서 3개를 뽑는 모든 조합을 확인
Combination comb = new Combination(spaces.size(), 3);
comb.combination(spaces, 0, 0, 0);
ArrayList<ArrayList<Position>> spaceList = comb.getResult();
// 학생이 한 명도 감지되지 않도록 설치할 수 있는지의 여부
boolean found = false;
for (int i = 0; i < spaceList.size(); i++) {
// 장애물들을 설치해보기
for (int j = 0; j < spaceList.get(i).size(); j++) {
int x = spaceList.get(i).get(j).getX();
int y = spaceList.get(i).get(j).getY();
board[x][y] = 'O';
}
// 학생이 한 명도 감지되지 않는 경우
if (!process()) {
// 원하는 경우를 발견한 것임
found = true;
break;
}
// 설치된 장애물을 다시 없애기
for (int j = 0; j < spaceList.get(i).size(); j++) {
int x = spaceList.get(i).get(j).getX();
int y = spaceList.get(i).get(j).getY();
board[x][y] = 'X';
}
}
if (found) System.out.println("YES");
else System.out.println("NO");
}
}
인구 이동 (삼성)
class Position {
private int x;
private int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
}
public class Main {
// 땅의 크기(N), L, R 값을 입력받기
public static int n, l, r;
public static int totalCount = 0;
// 전체 나라의 정보(N x N)를 입력받기
public static int[][] graph = new int[50][50];
public static int[][] unions = new int[50][50];
public static int[] dx = {-1, 0, 1, 0};
public static int[] dy = {0, -1, 0, 1};
// 특정 위치에서 출발하여 모든 연합을 체크한 뒤에 데이터 갱신
public static void process(int x, int y, int index) {
// (x, y)의 위치와 연결된 나라(연합) 정보를 담는 리스트
ArrayList<Position> united = new ArrayList<>();
united.add(new Position(x, y));
// 너비 우선 탐색 (BFS)을 위한 큐 라이브러리 사용
Queue<Position> q = new LinkedList<>();
q.offer(new Position(x, y));
unions[x][y] = index; // 현재 연합의 번호 할당
int summary = graph[x][y]; // 현재 연합의 전체 인구 수
int count = 1; // 현재 연합의 국가 수
// 큐가 빌 때까지 반복(BFS)
while (!q.isEmpty()) {
Position pos = q.poll();
x = pos.getX();
y = pos.getY();
// 현재 위치에서 4가지 방향을 확인하며
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
// 바로 옆에 있는 나라를 확인하여
if (0 <= nx && nx < n && 0 <= ny && ny < n && unions[nx][ny] == -1) {
// 옆에 있는 나라와 인구 차이가 L명 이상, R명 이하라면
int gap = Math.abs(graph[nx][ny] - graph[x][y]);
if (l <= gap && gap <= r) {
q.offer(new Position(nx, ny));
// 연합에 추가하기
unions[nx][ny] = index;
summary += graph[nx][ny];
count += 1;
united.add(new Position(nx, ny));
}
}
}
}
// 연합 국가끼리 인구를 분배
for (int i = 0; i < united.size(); i++) {
x = united.get(i).getX();
y = united.get(i).getY();
graph[x][y] = summary / count;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
l = sc.nextInt();
r = sc.nextInt();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
graph[i][j] = sc.nextInt();
}
}
// 더 이상 인구 이동을 할 수 없을 때까지 반복
while (true) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
unions[i][j] = -1;
}
}
int index = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (unions[i][j] == -1) { // 해당 나라가 아직 처리되지 않았다면
process(i, j, index);
index += 1;
}
}
}
// 모든 인구 이동이 끝난 경우
if (index == n * n) break;
totalCount += 1;
}
// 인구 이동 횟수 출력
System.out.println(totalCount);
}
}
블록 이동하기 (카카오)
class Node {
private int pos1X;
private int pos1Y;
private int pos2X;
private int pos2Y;
private int distance;
public int getPos1X() {
return this.pos1X;
}
public int getPos1Y() {
return this.pos1Y;
}
public int getPos2X() {
return this.pos2X;
}
public int getPos2Y() {
return this.pos2Y;
}
public int getDistance() {
return this.distance;
}
public Node(int pos1X, int pos1Y, int pos2X, int pos2Y, int distance) {
this.pos1X = pos1X;
this.pos1Y = pos1Y;
this.pos2X = pos2X;
this.pos2Y = pos2Y;
this.distance = distance;
}
}
class Solution {
public ArrayList<Node> getNextPos(Node pos, int[][] board) {
// 반환 결과(이동 가능한 위치들)
ArrayList<Node> nextPos = new ArrayList<Node>();
// (상, 하, 좌, 우)로 이동하는 경우에 대해서 처리
int[] dx = {-1, 1, 0, 0};
int[] dy = {0, 0, -1, 1};
for (int i = 0; i < 4; i++) {
int pos1NextX = pos.getPos1X() + dx[i];
int pos1NextY = pos.getPos1Y() + dy[i];
int pos2NextX = pos.getPos2X() + dx[i];
int pos2NextY = pos.getPos2Y() + dy[i];
int distanceNext = pos.getDistance() + 1;
// 이동하고자 하는 두 칸이 모두 비어 있다면
if (board[pos1NextX][pos1NextY] == 0 && board[pos2NextX][pos2NextY] == 0) {
nextPos.add(new Node(pos1NextX, pos1NextY, pos2NextX, pos2NextY, distanceNext));
}
}
// 현재 로봇이 가로로 놓여 있는 경우
int[] hor = {-1, 1};
if (pos.getPos1X() == pos.getPos2X()) {
for (int i = 0; i < 2; i++) { // 위쪽으로 회전하거나, 아래쪽으로 회전
// 위쪽 혹은 아래쪽 두 칸이 모두 비어 있다면
if (board[pos.getPos1X() + hor[i]][pos.getPos1Y()] == 0 && board[pos.getPos2X() + hor[i]][pos.getPos2Y()] == 0) {
nextPos.add(new Node(pos.getPos1X(), pos.getPos1Y(), pos.getPos1X() + hor[i], pos.getPos1Y(), pos.getDistance() + 1));
nextPos.add(new Node(pos.getPos2X(), pos.getPos2Y(), pos.getPos2X() + hor[i], pos.getPos2Y(), pos.getDistance() + 1));
}
}
}
// 현재 로봇이 세로로 놓여 있는 경우
int[] ver = {-1, 1};
if (pos.getPos1Y() == pos.getPos2Y()) {
for (int i = 0; i < 2; i++) { // 왼쪽으로 회전하거나, 오른쪽으로 회전
// 왼쪽 혹은 오른쪽 두 칸이 모두 비어 있다면
if (board[pos.getPos1X()][pos.getPos1Y() + ver[i]] == 0 && board[pos.getPos2X()][pos.getPos2Y() + ver[i]] == 0) {
nextPos.add(new Node(pos.getPos1X(), pos.getPos1Y(), pos.getPos1X(), pos.getPos1Y() + ver[i], pos.getDistance() + 1));
nextPos.add(new Node(pos.getPos2X(), pos.getPos2Y(), pos.getPos2X(), pos.getPos2Y() + ver[i], pos.getDistance() + 1));
}
}
}
// 현재 위치에서 이동할 수 있는 위치를 반환
return nextPos;
}
public int solution(int[][] board) {
// 맵 외곽에 벽을 두는 형태로 맵 변형
int n = board.length;
int[][] newBoard = new int[n + 2][n + 2];
for (int i = 0; i < n + 2; i++) {
for (int j = 0; j < n + 2; j++) {
newBoard[i][j] = 1;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
newBoard[i + 1][j + 1] = board[i][j];
}
}
// 너비 우선 탐색(BFS) 수행
Queue<Node> q = new LinkedList<>();
ArrayList<Node> visited = new ArrayList<>();
Node pos = new Node(1, 1, 1, 2, 0); // 시작 위치 설정
q.offer(pos); // 큐에 삽입한 뒤에
visited.add(pos); // 방문 처리
// 큐가 빌 때까지 반복
while (!q.isEmpty()) {
pos = q.poll();
// (n, n) 위치에 로봇이 도달했다면, 최단 거리이므로 반환
if ((pos.getPos1X() == n && pos.getPos1Y() == n) || (pos.getPos2X() == n && pos.getPos2Y() == n)) {
return pos.getDistance();
}
// 현재 위치에서 이동할 수 있는 위치 확인
ArrayList<Node> nextPos = getNextPos(pos, newBoard);
for (int i = 0; i < nextPos.size(); i++) {
// 아직 방문하지 않은 위치라면 큐에 삽입하고 방문 처리
boolean check = true;
pos = nextPos.get(i);
for (int j = 0; j < visited.size(); j++) {
if (pos.getPos1X() == visited.get(j).getPos1X() && pos.getPos1Y() == visited.get(j).getPos1Y() && pos.getPos2X() == visited.get(j).getPos2X() && pos.getPos2Y() == visited.get(j).getPos2Y()) {
check = false;
break;
}
}
if (check) {
q.offer(pos);
visited.add(pos);
}
}
}
return 0;
}
}
728x90
반응형
'Language > Java' 카테고리의 다른 글
구현 - 아이디어를 코드로 바꾸는 구현 (0) | 2021.05.05 |
---|---|
그리디 - 당장 좋은 것만 선택하는 그리디 (0) | 2021.05.05 |
[함수형 프로그래밍] lambda, functional interface, method reference (0) | 2021.04.23 |
Java 컬렉션(Collection) (0) | 2021.04.22 |
Java 자료형 (0) | 2021.04.22 |