Topics
- 완전탐색 I
완전탐색 I
이번 조별과제는 완전탐색에 대해서 공부하였다. 그 중에서도 자리 수, 구간 단위로 완전탐색을 하고 자리마다 숫자를 정하는 완전탐색에 대해서 공부하였다. 그 중에서 어려웠던 내용이나 중요한 내용 몇 가지를 추려서 말하고자 한다.
1. 오목
import java.util.Scanner;
public class Main {
private static final int SIZE = 19;
private static final int[][] DIRECTIONS = {
{0, 1}, // 오른쪽
{1, 0}, // 아래쪽
{1, 1}, // 오른쪽 아래 대각선
{1, -1} // 왼쪽 아래 대각선
};
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[][] board = new int[SIZE][SIZE];
// 바둑판 상태 입력
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
board[i][j] = scanner.nextInt();
}
}
// 승리 여부 확인
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (board[i][j] != 0) {
int winner = board[i][j];
if (checkWin(board, i, j, winner)) {
System.out.println(winner);
int[] winningPosition = findWinningPosition(board, i, j, winner);
System.out.println((winningPosition[0] + 1) + " " + (winningPosition[1] + 1));
return;
}
}
}
}
// 승부가 결정되지 않음
System.out.println(0);
}
// 주어진 위치에서 승리 조건을 만족하는지 확인하는 함수
private static boolean checkWin(int[][] board, int x, int y, int player) {
for (int[] direction : DIRECTIONS) {
int count = 1;
int dx = direction[0];
int dy = direction[1];
// 한 방향으로 연속된 바둑알 개수 세기
for (int step = 1; step < 5; step++) {
int nx = x + dx * step;
int ny = y + dy * step;
if (nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE && board[nx][ny] == player) {
count++;
} else {
break;
}
}
// 반대 방향으로 연속된 바둑알 개수 세기
for (int step = 1; step < 5; step++) {
int nx = x - dx * step;
int ny = y - dy * step;
if (nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE && board[nx][ny] == player) {
count++;
} else {
break;
}
}
// 연속된 바둑알이 5개인 경우 승리
if (count == 5) {
return true;
}
}
return false;
}
// 승리한 바둑알의 위치를 찾는 함수
private static int[] findWinningPosition(int[][] board, int x, int y, int player) {
for (int[] direction : DIRECTIONS) {
int count = 1;
int dx = direction[0];
int dy = direction[1];
int startX = x;
int startY = y;
// 한 방향으로 연속된 바둑알 개수 세기
for (int step = 1; step < 5; step++) {
int nx = x + dx * step;
int ny = y + dy * step;
if (nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE && board[nx][ny] == player) {
count++;
startX = nx;
startY = ny;
} else {
break;
}
}
// 반대 방향으로 연속된 바둑알 개수 세기
for (int step = 1; step < 5; step++) {
int nx = x - dx * step;
int ny = y - dy * step;
if (nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE && board[nx][ny] == player) {
count++;
} else {
break;
}
}
// 연속된 바둑알이 5개인 경우, 시작점과 끝점 중간의 위치 반환
if (count == 5) {
int midX = (x + startX) / 2;
int midY = (y + startY) / 2;
return new int[]{midX, midY};
}
}
return new int[]{x, y}; // 기본값으로 현재 위치 반환
}
}
문제에서 주어진 조건에 맞추어, 오목이 변환하는 규칙을 따라 위치를 변환하고, 위치를 찾는 알고리즘을 작성하였다.
2. G or H
import java.util.Scanner;
public class Main {
public static final int MAX_NUM = 100;
public static int n, k;
public static int[] arr = new int[MAX_NUM + 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();
char c = sc.next().charAt(0);
if(c == 'G')
arr[x] = 1;
else
arr[x] = 2;
}
// 모든 구간의 시작점을 잡아봅니다.
int maxLen = 0;
for(int i = 0; i <= MAX_NUM; i++) {
for(int j = i + 1; j <= MAX_NUM; j++) {
// i와 j 위치에 사람이 있는지 확인합니다.
if(arr[i] == 0 || arr[j] == 0)
continue;
// 해당 구간 내 g와 h의 개수를 구합니다.
int cntG = 0;
int cntH = 0;
for(int k = i; k <= j; k++) {
if(arr[k] == 1)
cntG++;
if(arr[k] == 2)
cntH++;
}
// 조건을 만족할 때 구간의 길이를 구해 최댓값과 비교합니다.
if(cntG == 0 || cntH == 0 || cntG == cntH) {
int len = j - i;
maxLen = Math.max(maxLen, len);
}
}
}
System.out.print(maxLen);
}
}
최대 사진의 크기를 구하는 알고리즘으로, 시작점과 사람이 있는지 없는지를 판단하는 변수를 통하여 구간의 길이를 구해서
최댓값과 비교하여 더 큰 값을 찾았다.
3. 개발자의 능력
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 6명의 능력을 입력받습니다.
int[] abilities = new int[6];
for (int i = 0; i < 6; i++) {
abilities[i] = scanner.nextInt();
}
// 가능한 모든 팀 조합을 생성합니다.
List<int[][]> teams = generateTeams(abilities);
// 팀 간의 능력 차이를 최소화합니다.
int minDifference = Integer.MAX_VALUE;
for (int[][] team : teams) {
int sum1 = abilities[team[0][0]] + abilities[team[0][1]];
int sum2 = abilities[team[1][0]] + abilities[team[1][1]];
int sum3 = abilities[team[2][0]] + abilities[team[2][1]];
int maxSum = Math.max(sum1, Math.max(sum2, sum3));
int minSum = Math.min(sum1, Math.min(sum2, sum3));
int difference = maxSum - minSum;
minDifference = Math.min(minDifference, difference);
}
// 최소 차이를 출력합니다.
System.out.println(minDifference);
}
// 가능한 모든 팀 조합을 생성하는 함수
private static List<int[][]> generateTeams(int[] abilities) {
List<int[][]> teams = new ArrayList<>();
int[] indices = {0, 1, 2, 3, 4, 5};
generateCombinations(indices, 0, teams);
return teams;
}
// 조합을 생성하는 함수
private static void generateCombinations(int[] indices, int start, List<int[][]> teams) {
if (start == indices.length) {
int[][] team = new int[3][2];
team[0][0] = indices[0];
team[0][1] = indices[1];
team[1][0] = indices[2];
team[1][1] = indices[3];
team[2][0] = indices[4];
team[2][1] = indices[5];
teams.add(team);
return;
}
for (int i = start; i < indices.length; i++) {
swap(indices, start, i);
generateCombinations(indices, start + 1, teams);
swap(indices, start, i);
}
}
// 배열의 두 요소를 교환하는 함수
private static void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
팀원들의 능력 총합이 큰 차이와 작은 차이의 갭을 최소화하여 균형있게 구성하였다.
'Algorithm' 카테고리의 다른 글
Baekjoon - 정렬 (1) | 2024.10.01 |
---|---|
Baekjoon - Brute-Force (5) | 2024.09.18 |
Baekjoon Time-complexity (1) | 2024.09.18 |
[코드트리 조별과제] 2 Days - TIL (1) | 2024.08.04 |
[Code tree 조별과제] (1) | 2024.07.21 |