문제

https://www.acmicpc.net/problem/2477

분석/설계

최대 넓이를 가지는 가로 * 세로를 구하고 

최소 넓이를 가지는 가로*세로를 구하여 최대 넓이 - 최소 넓이 빼주고

거기에 참외수를 곱하여 방식으로 처음에 생각하고 접근하였습니다.

 

1. 입력받은 문자열을 각각의 문자로 쪼개 확인합니다.

2. 최대 넓이를 가지는 가로, 세로의 길이 각 입력 값을 받아 방향에 따라 각각의 최대 값을 구해주면 됩니다.

3. 최소 넓이는 꺽이는 부분을 고려하여, 아래와 같이 정의하고 i 위치에따른 이전 변과 다음 변의 방향이 같으면

    i는 최소 넓이를 구하는 가로 또는 세로 중에 하나이므로 이를 저장합니다.

4. 마지막으로 구해진 최대, 최소 가로와 세로 값 그리고 참외 수를 곱해서 결과 값을 구합니다.

구현 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int K = Integer.parseInt(br.readLine());
		int maxHeight = 0;
		int maxWidth = 0;
		int minHeight = 0;
		int minWidth = 0;
		
		int[] dirArr = new int[6];
		int[] distArr = new int[6];
		
		for(int i=0; i<6; i++) { // 1. 입력받은 문자열을 각각의 문자로 쪼개 확인합니다.
			String[] input = br.readLine().split(" ");
			dirArr[i] = Integer.parseInt(input[0]);
			distArr[i] = Integer.parseInt(input[1]);
			
            // 2. 최대 넓이를 가지는 가로, 세로의 길이 각 입력 값을 받아 방향에 따라 각각의 최대 값을 구해주면 됩니다.
			if (dirArr[i] == 1 || dirArr[i] == 2) { 
				maxWidth = Math.max(maxWidth, distArr[i]);
			} else {
				maxHeight = Math.max(maxHeight, distArr[i]);
			}
		}
			
        // 3. 최소 넓이는 꺽이는 부분을 고려하여, 아래와 같이 정의하고 i 위치에따른 이전 변과 다음 변의 방향이 같으면
        // i는 최소 넓이를 구하는 가로 또는 세로 중에 하나이므로 이를 저장합니다.
		for(int i=0; i<6; i++) { // 최소 넓이를 가진 넓이를 구한다.
			// i를 최소 넓이의 가로 또는 세로라고 가정한다.
			int before = (i+5) % 6; 
			int after  = (i+1) % 6;
			
			if (dirArr[before] == dirArr[after]) { // i 기준으로 이전과 다음에 나올 변의 방향이 같으면
				if (dirArr[i] == 1 || dirArr[i] == 2) { // 방향에 따라 가장 작은 크기 가로, 세로 
					minWidth = distArr[i];
				} else {
					minHeight = distArr[i];
				}
			}
		}
		
        // 4. 마지막으로 구해진 최대, 최소 가로와 세로 값 그리고 참외 수를 곱해서 결과 값을 구합니다.
		int result = (maxHeight * maxWidth - minHeight * minWidth) * K; // (최대 넓이 - 최소 넓이) * 참외 개수 
		System.out.println(result);
	}
}

정리

최소 넓이의 가로 세로를 어떤식으로 기준을 잡고 구할지가 쉽게 떠오르지 않습니다.

문제에 주어진 조건을 잘 확인하고 고민해봐야합니다.

참고

https://www.acmicpc.net/problem/2477

'Algorithm > 구현' 카테고리의 다른 글

[백준] 배열돌리기 1  (0) 2022.12.23
[백준] 마인크래프트  (0) 2022.12.23
괄호의 값  (1) 2022.12.14
구현 - 문자열 재정렬  (0) 2022.03.17

문제

https://www.acmicpc.net/problem/16926

분석/설계

회전을 할 각 라인의 개수와 구한 각 라인을 반복하여 회전시켜야합니다.

 

1. 입력받은 문자열을 각각의 문자로 쪼개 확인합니다.

2. 회전을 할 각 라인의 개수를 구합니다.

    2X2  = 2개, 4X4 = 2개, 5x4 = 2개, 6x4 = 2개....

    Math.min(N, M) / 2  

3. 구한 각 라인을 반복하여 회전시킵니다.

   이때 회전하는 방향을 유의해야하고 각 시작점(0,0) ... (1,1)는 임시 변수에 저장했다가 이동한 위치로 (1,0) ... (2,1)

   반복이 끝날때 값을 넣어줍니다. 

 

구현 코드

import java.util.Scanner;

public class Main {
	static int M, N, R; // 가로, 새로, 회전 수
	static int [][] arr;
	static int[] dx = {0, 1, 0, -1}; 
	static int[] dy = {1, 0, -1, 0};
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		// 1. 입력받은 문자열을 각각의 문자로 쪼개 확인합니다.
		N = sc.nextInt();
		M = sc.nextInt();
		R = sc.nextInt();
		arr = new int[N][M];
		
		for (int i=0; i<N; i++) {
			for (int j=0; j<M; j++) {
				arr[i][j] = sc.nextInt(); 
			}
		}
		
        // 2. 회전을 할 각 라인의 개수를 구합니다.
		int line = Math.min(N, M) / 2;
		
        // 3. 구한 각 라인을 반복하여 회전시킵니다.
		for (int i=0; i<R; i++) { 
			for (int j=0; j<line; j++) { 
				int x = j;
				int y = j;
				int val = arr[x][y];
				int idx = 0;
				
				while(idx<4) {
					int mx = x + dx[idx];
					int my = y + dy[idx];
					
					if (mx >= j && mx < N-j && my >= j && my < M-j) {
						arr[x][y] = arr[mx][my];
						x = mx;
						y = my;
					} else {
						idx++;
					}	
				}
				arr[j+1][j] = val;
			}
		}
		
		for (int i=0; i<N; i++) {
			for(int j=0; j<M; j++) {
				System.out.print(arr[i][j] + " ");
			}
			System.out.println();
		}
		
		sc.close();
	}
}

정리

각 라인 별로 어떻게 값 이동을 구현할지를 각 라인의 수를 어떻게 구할지 

처음 접하면 떠오르지 않습니다. 

기존 맵의 탐색하는 유형은 많이 만나봐서 그런 방식으로 접근을 했고,

각 라인의 범위를 침범하지 않은 채로 이동을 해야했기때문에 많은 고심을 한 문제입니다.

백준 사이트에 보면 이런 유형의 문제가 많으니 많이 접해보고 다른분들의 풀이도 보면 도움이 되지 않을까 싶습니다.

참고

https://www.acmicpc.net/problem/16926

'Algorithm > 구현' 카테고리의 다른 글

[백준] 참외밭  (0) 2022.12.23
[백준] 마인크래프트  (0) 2022.12.23
괄호의 값  (1) 2022.12.14
구현 - 문자열 재정렬  (0) 2022.03.17

문제

https://www.acmicpc.net/problem/18111

분석/설계

답이 여러개인 경우 땅의 높이가 가장 높은 것을 골라야한다는 것을 염두해두어야함.

 

1. 입력받은 문자열을 각각의 문자로 쪼개 확인합니다.

2. 맵 상에 블록 높이의 최소 값과 최대값을 구합니다.

3. 최소~최대 높이의 수 만큼 반복문을 만듭니다.

   3.1 맵의 크기만큼 반복문을 만들고 맵의 높이 - (최소 값~최대 높이 )를 차이를 구합니다.

   3.2 차이가 0보다 클 경우 시간과 인벤토리에 차이값을 더해줍니다.

   3.3 차이가 0보다 작을 경우 시간과 인벤토리에 차이값을 더하고 빼줍니다.

   3.4 구한 값들을 반복문이 끝날때까지 결과값에 갱신합니다.

4. 결과값을 출력합니다.

 

구현 코드

import java.util.*;
import java.io.*;

public class Main {
	public static void main(String[] args) throws IOException {
    	// 입력을 Scanner 로 받을 경우 시간 초과
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String[] nmb = br.readLine().split(" ");
        int N = Integer.parseInt(nmb[0]);
        int M = Integer.parseInt(nmb[1]);
        int B = Integer.parseInt(nmb[2]);
		int[][ ]map = new int[N][M];
		
		int min = Integer.MAX_VALUE;
		int max = Integer.MIN_VALUE;
		
		for(int i=0; i<N; i++) { // 변수를 초기화 하면서 최대값, 최소값을 구한다.
            String[] mapRow = br.readLine().split(" ");
			for(int j=0; j<M; j++) {
				int input = Integer.parseInt(mapRow[j]);
				map[i][j] = input;
				max = Math.max(max, input);
				min = Math.min(min, input);
			}
		}
		
		int minTime = Integer.MAX_VALUE; 
		int height = 0; 
		
		for (int i=min; i<=max; i++) { // 최소~최대까지 루프
			int time = 0;
			int inventory = B;
			int diff = 0;
			
			for (int j=0; j<N; j++) {
				for (int k=0; k<M; k++) {
					if (map[j][k] > i) { // 값이 클 경우
						diff = map[j][k]-i; // 차이 값을 구함
						time += diff * 2; // 시간에 (+)
						inventory += diff; // 인벤토리에 (+)
					} else if(map[j][k] < i) { // 값이 작을 경우
						diff = i- map[j][k]; // 차이 값을 구함
						time += diff; // 시간에 (+)
						inventory -= diff; // 인벤토리에 (-)
					}
				}
			}
			
			if(inventory >= 0 && minTime >= time) { // 최소 시간과 높이를 갱신
				minTime = time;
				height = i;
			}
		}
		
		System.out.println(minTime + " " + height);
	}
}

정리

입력받을 시 Scanner를 사용할 경우 백준 채점 사이트에서 시간초과를 만나게됩니다.

Scanner 대신 BufferedReader를 통해 입력을 받아야합니다.

Scanner는 1KB 버퍼 BufferedReader 는 8KB 버퍼로 차이가 있기때문에 입력 값이 많을수록 성능 차이가 있습니다.

참고

https://dlee0129.tistory.com/238

https://www.acmicpc.net/problem/18111

'Algorithm > 구현' 카테고리의 다른 글

[백준] 참외밭  (0) 2022.12.23
[백준] 배열돌리기 1  (0) 2022.12.23
괄호의 값  (1) 2022.12.14
구현 - 문자열 재정렬  (0) 2022.03.17

문제

https://www.acmicpc.net/problem/2504

분석/설계

Stack 자료구조를 활용하여, 문제의 조건들을 구현 가능합니다.

 

1. 입력받은 문자열을 각각의 문자로 쪼개 확인합니다.

2. 문자의 각 괄호가 '(' , '[' 이면 2, 3을 곱해줍니다.

3. 문자의 괄호가 ')'의 경우

    3.1 스택이 비어있거나 '('이 없는 경우 결과 값을 0으로 수정.

    3.2 이전 문자 값이 '('  일 경우 결과 값에 더해주고, Stack에서 제거.

4. 문자의 괄호가 ']' 경우

    4.1 스택이 비어있거나 '['이 없는 경우 결과 값을 0으로 수정.

    4.2 이전 문자 값이 '['  일 경우 결과 값에 더해주고, Stack에서 제거.

 

구현 코드

import java.util.Scanner;
import java.util.Stack;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str = sc.next();
		Stack<Character> stack = new Stack<>();
		
		int res = 0;
		int val = 1;
		
		for (int i=0; i<str.length(); i++) {
			char c = str.charAt(i);
			if (c == '(' ) {
				stack.push(c);
				val *= 2;
			} else if(c == '[') {
				stack.push(c);
				val *= 3;
			} else if(c == ')') {
				if(stack.isEmpty() || stack.peek() != '(') {
					res = 0;
					break;
				} else if(str.charAt(i-1) == '(') {
					res += val;
				}
				stack.pop();
				val /= 2;
			} else if(c == ']') {
				if(stack.isEmpty() || stack.peek() != '[') {
					res = 0;
					break;
				} else if(str.charAt(i-1) == '[') {
					res += val;
				}
				stack.pop();
				val /= 3;
			}
		}
		
		if(!stack.isEmpty()) {
			res = 0;
		} 
		System.out.println(res);
		sc.close();	
	}
}

정리

조건들을 잘 읽고 어떻게 구현할지 쪼개서 생각해봐야 합니다.

Java에서 Stack과 문자열 다루는 메서드들에 대해서는 익숙해질 필요가 있습니다.

  • push(item): item 하나를 스택의 가장 윗부분에 삽입.
  • peek(): 스택의 가장 위에 있는 항목을 반환.
  • pop(): 스택에서 가장 위에 있는 항목을 삭제하고 해당 item을 반환.
  • isEmpty(): 스택이 비어있는지 유무에 따라 true/false를 반환.

참고

https://www.acmicpc.net/problem/2504

'Algorithm > 구현' 카테고리의 다른 글

[백준] 참외밭  (0) 2022.12.23
[백준] 배열돌리기 1  (0) 2022.12.23
[백준] 마인크래프트  (0) 2022.12.23
구현 - 문자열 재정렬  (0) 2022.03.17

문제

https://www.acmicpc.net/problem/4963

분석/설계

맵을 탐색하는 DFS/BFS 유형의 문제이고 보통 2차원 배열 형태의 맵을 주고 조건을 달리하면서

탐색하는 형태 유형으로 많이 출제되는 것 같습니다.

기존 상하좌우만 탐색하는 케이스와 달리 대각선까지 탐색하기 때문에 이를 탐색하기 위한 값들을 잘 정의해줘야합니다.

구현 코드

package backjoon;

import java.util.Scanner;

public class Main {
	static int T; // 테스트 케이스 횟수
	static int M; // 배추 심어진 가로 길이
	static int N; // 배추 심어진 세로 개수
	static int K; // 배추가 심어진 위치의 개수
	static int[][] map; // 배추밭
	static boolean[][] visited; //
	static int cnt; // 필요한 지렁이 
	static int[] dx = {0, -1, 0, 1}; // 상하좌우 탐색을 위한 값들
	static int[] dy = {1, 0, -1, 0};
	
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		T = scanner.nextInt(); // 테스트 케이스 개수
		
		for(int i=0; i<T; i++) {	// 입력 초기화
			cnt = 0;
			M = scanner.nextInt();
			N = scanner.nextInt();
			K = scanner.nextInt();
			
			map = new int[M][N];
			visited = new boolean[M][N];
			
			for(int j=0; j<K; j++) {
				int x = scanner.nextInt();
				int y = scanner.nextInt();	
				map[x][y] = 1;
			}
			
			for(int v=0; v<M; v++) {
				for(int w=0; w<N; w++) {
					if (map[v][w] == 1 && !visited[v][w]) {
						dfs(v, w);
						cnt++;
					}
				}
			}
			System.out.println(cnt);

		}
		scanner.close();
	}
	
	public static void dfs(int x, int y) {
		visited[x][y] = true;
		
		for(int i=0; i<4; i++) {
			int mx = x + dx[i];
			int my = y + dy[i];
			
			if (mx >= 0 && my >= 0 && mx < M && my < N) { // 0 보다 크고 맵 크기보다는 작아야한다.
				if(!visited[mx][my] && map[mx][my] == 1) { // 방문 여부와 배추가 심어진 곳을 체크
					dfs(mx, my);
				}
			}
		}
	}
}

 

정리

입력받는 변수가 여러 개이므로 놓치지 않고 어떤 변수에 저장할지 정리하여

DFS 구현에 필요한 변수와 함께 정의합니다.

그 외에  탐색을 위한 값들도 정의해주고 이를 DFS 구현 시 적용하는 게 핵심입니다.

구현이 끝나면  간단하지만 어떻게 탐색하고 카운트할지 고민하고 구현에 들어가야 합니다.

참고

https://www.acmicpc.net/problem/4963

'Algorithm > DFS|BFS' 카테고리의 다른 글

DFS/BFS - 연결 요소의 개수  (0) 2022.12.14
DFS/BFS - 유기농 배추  (0) 2022.12.08
DFS/BFS - 바이러스  (0) 2022.05.11
DFS/BFS - 단지번호붙이기  (0) 2022.04.19
DFS/BFS - DFS와 BFS  (0) 2022.04.16

문제

https://www.acmicpc.net/problem/11724

분석/설계

그래프를 탐색하는 DFS/BFS 유형의 문제입니다.

구현 시 주의할 점은 방문을 체크하는 배열을 크기를 +1 해줘야 합니다.

그렇지 않을 경우 조건에서 N이 1부터 시작하기 때문에 마지막 수를 체크할 때  

Array 크기를 초과하여 Exception이 발생하게 됩니다.

구현 코드

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {
	static int N; // 정점 개수
	static int M; // 간선 개수
	static boolean[] visited; // 방문한 곳
	static ArrayList<ArrayList<Integer>> map = new ArrayList<>(); // 그래프
	static int cnt; // 연결 요소의 개수 
	
	public static void dfs(int v) {
		visited[v] = true;
		
		for (int i=0; i<map.get(v).size(); i++) {
			int w = map.get(v).get(i);
			if (!visited[w]) dfs(w);
		}
	}
	
	public static void bfs(int v) {
		Queue<Integer> queue = new LinkedList<>();
		queue.offer(v);

		visited[v] = true;
		
		while(!queue.isEmpty()) {
			int x= queue.poll();
		
			for (int i=0; i<map.get(v).size(); i++) {
				int w = map.get(x).get(i);
				if(!visited[w]) {
					queue.offer(w);
					visited[w] = true;
				}	
			}
			
		}
		
	}
	
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		
		N = scanner.nextInt();
		M = scanner.nextInt();
		
		for(int i=0; i<=N; i++) {
			map.add(new ArrayList<>());
		}
		
		visited = new boolean[N+1];
		
		for (int i=0; i<M; i++) {
			int v1 = scanner.nextInt();
			int v2 = scanner.nextInt();
			map.get(v1).add(v2);
			map.get(v2).add(v1);
		}
		
		for(int i=1; i<=N; i++) {
			if(!visited[i]) {
				dfs(i);
				cnt++;
			}
		}	
		System.out.println(cnt);
		scanner.close();
	}
}

정리

간단하지만 조건을 정확하게 확인해야 실수를 줄일 수 있습니다.

참고

https://www.acmicpc.net/problem/11724

'Algorithm > DFS|BFS' 카테고리의 다른 글

DFS/BFS - 섬의개수  (0) 2022.12.14
DFS/BFS - 유기농 배추  (0) 2022.12.08
DFS/BFS - 바이러스  (0) 2022.05.11
DFS/BFS - 단지번호붙이기  (0) 2022.04.19
DFS/BFS - DFS와 BFS  (0) 2022.04.16

+ Recent posts