문제 설명

1. 색칠되지 않은 영역의 개수와 넓이를 구하면 되는 문제다.

풀이

처음에는 색칠된 영역에서 나눠진 그룹별로 넓이를 구하는건줄 알았는데 색칠되지 않은 영역을 구하는 문제였다.
색칠된 영역은 영역끼리 구분될 필요가 없으므로 true 로 설정했고, false 인것끼리 dfs 를 했다.
bfs 를 사용하지 않은 이유
1. dfs 로 하면 영역별로 나누는게 쉽다. (재귀함수기 때문에 한 번 확인하는 영역은 끝을 봄)
2. dfs 안에 bfs 를 넣을 수 있었는데 귀찮았다.
PriorityQueue (max-heap) 를 사용한 이유
1. 원래는 LinkedList 를 사용하려 했었는데 정렬을 해야되서 귀찮았다.
2. 하나씩 앞에서 꺼내쓰는게 queue 랑 맞다고 생각했기 때문이다.

결론적으로 풀이 방법은
1. dfs 를 이용해서 모든 구역을 확인하고 각 영역별로 넓이를 큐에 담아줬다.
2. 큐에 담겨진 데이터의 개수를 모드 출력하고 데이터를 순차적으로 출력했다.

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/2583
* BOJ 백준온라인져지 2583 영역 구하기 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
private static PriorityQueue<Integer> result = new PriorityQueue<>();
private static int N, M;
private static boolean map[][], visited[][];
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
int K = Integer.parseInt(st.nextToken());
map = new boolean[N][M];
visited = new boolean[N][M];
for (int i = 0; i < K; i++) {
st = new StringTokenizer(br.readLine());
int x1 = Integer.parseInt(st.nextToken());
int y1 = Integer.parseInt(st.nextToken());
int x2 = Integer.parseInt(st.nextToken());
int y2 = Integer.parseInt(st.nextToken());
for (int j = x1; j < x2; j++) {
for (int k = y1; k < y2; k++) {
map[k][j] = true;
}
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (!map[i][j] && !visited[i][j]) result.offer(dfs(i, j));
}
}
bw.write(String.valueOf(result.size()));
bw.write("\n");
while (!result.isEmpty()) {
bw.write(String.valueOf(result.poll()));
bw.write(" ");
}
bw.flush();
}
private static int xxxx[] = { -1, 0, 1, 0 };
private static int yyyy[] = { 0, 1, 0, -1 };
private static int dfs (int x, int y) {
visited[x][y] = true;
int result = 1;
for (int i = 0; i < 4; i++) {
int curX = x + xxxx[i];
int curY = y + yyyy[i];
if (curX < 0 || curY < 0 || curX >= N || curY >= M || visited[curX][curY] || map[curX][curY]) continue;
result += dfs(curX, curY);
}
return result;
}
}
view raw Main.java hosted with ❤ by GitHub

문제

눈금의 간격이 1인 M×N(M,N≤100)크기의 모눈종이가 있다. 이 모눈종이 위에 눈금에 맞추어 K개의 직사각형을 그릴 때, 이들 K개의 직사각형의 내부를 제외한 나머지 부분이 몇 개의 분리된 영역으로 나누어진다.

예를 들어 M=5, N=7 인 모눈종이 위에 <그림 1>과 같이 직사각형 3개를 그렸다면, 그 나머지 영역은 <그림 2>와 같이 3개의 분리된 영역으로 나누어지게 된다.

<그림 2>와 같이 분리된 세 영역의 넓이는 각각 1, 7, 13이 된다.

M, N과 K 그리고 K개의 직사각형의 좌표가 주어질 때, K개의 직사각형 내부를 제외한 나머지 부분이 몇 개의 분리된 영역으로 나누어지는지, 그리고 분리된 각 영역의 넓이가 얼마인지를 구하여 이를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 M과 N, 그리고 K가 빈칸을 사이에 두고 차례로 주어진다. M, N, K는 모두 100 이하의 자연수이다. 둘째 줄부터 K개의 줄에는 한 줄에 하나씩 직사각형의 왼쪽 아래 꼭짓점의 x, y좌표값과 오른쪽 위 꼭짓점의 x, y좌표값이 빈칸을 사이에 두고 차례로 주어진다. 모눈종이의 왼쪽 아래 꼭짓점의 좌표는 (0,0)이고, 오른쪽 위 꼭짓점의 좌표는(N,M)이다. 입력되는 K개의 직사각형들이 모눈종이 전체를 채우는 경우는 없다.

출력

첫째 줄에 분리되어 나누어지는 영역의 개수를 출력한다. 둘째 줄에는 각 영역의 넓이를 오름차순으로 정렬하여 빈칸을 사이에 두고 출력한다.

예제 입력 1 

5 7 3
0 2 4 4
1 1 2 5
4 0 6 2

예제 출력 1 

3
1 7 13


조금 쉽게 풀어보려 했지만 실패

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/2523
* BOJ 백준온라인져지 2523 별찍기 - 13 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
for (int j = 1; j <= 2 * N - 1; j++) {
for (int i = 1; i <= (j < N ? j : 2 * N - j); i++) {
bw.write("*");
}
bw.write("\n");
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

  예제를 보고 별찍는 규칙을 유추한 뒤에 별을 찍어 보세요.

입력

  첫째 줄에 N (1<=N<=100) 주어진다.

출력

  첫째 줄부터 2*N-1번째  까지 차례대로 별을 출력한다.

예제 입력 1 

3

예제 출력 1 

*
**
***
**
*


문제 설명

1. 문자열이 입력된게 모두 맞으면 그대로 출력하면 되고 다른 부분은 ? 로 출력하면 된다.

풀이

1. 문자열의 길이는 모두 같으므로 0 번 째를 기준으로 비교한다. (하나라도 다른게 보인다면 그 부분은 다르므로 ? 처리)
2. 다른게 없으면 그대로 출력

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/1032
* BOJ 백준온라인져지 1032 명령 프롬프트 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
String str1[] = new String[N];
for (int i = 0; i < N; i++) str1[i] = br.readLine();
for (int i = 0; i < str1[0].length(); i++) {
int isNotEqual = 0;
for (int j = 1; j < N; j++) isNotEqual |= str1[0].charAt(i) - str1[j].charAt(i);
if (isNotEqual != 0) bw.write("?");
else bw.write(str1[0].charAt(i));
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

시작 -> 실행 -> cmd를 쳐보자. 검정 화면이 눈에 보인다. 여기서 dir이라고 치면 그 디렉토리에 있는 서브디렉토리와 파일이 모두 나온다. 이 때 원하는 파일을 찾으려면 다음과 같이 하면 된다.

dir *.exe라고 치면 확장자가 exe인 파일이 다 나온다. "dir 패턴"과 같이 치면 그 패턴에 맞는 파일만 검색 결과로 나온다. 예를 들어, dir a?b.exe라고 검색하면 파일명의 첫 번째 글자가 a이고, 세 번째 글자가 b이고, 확장자가 exe인 것이 모두 나온다. 이 때 두 번째 문자는 아무거나 나와도 된다. 예를 들어, acb.exe, aab.exe, apb.exe가 나온다.

이 문제는 검색 결과가 먼저 주어졌을 때, 패턴으로 뭘 쳐야 그 결과가 나오는지를 출력하는 문제이다. 패턴에는 알파벳과 "." 그리고 "?"만 넣을 수 있다. 가능하면 ?을 적게 써야 한다. 그 디렉토리에는 검색 결과에 나온 파일만 있다고 가정하고, 파일 이름의 길이는 모두 같다.

입력

첫째 줄에 파일 이름의 개수 N이 주어진다. 둘째 줄부터 N개의 줄에는 파일 이름이 주어진다. N은 50보다 작거나 같은 자연수이고 파일 이름의 길이는 모두 같고 길이는 최대 50이다. 파일이름은 알파벳과 "." 그리고 "?"로만 이루어져 있다.

출력

첫째줄에 패턴을 출력하면 된다.

예제 입력 1 

3
config.sys
config.inf
configures

예제 출력 1 

config????


import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/5543
* BOJ 백준온라인져지 5543 상근날드 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int burger = Integer.MAX_VALUE;
for (int i = 0; i < 3; i++) burger = Math.min(burger, Integer.parseInt(br.readLine()));
int drink = Integer.MAX_VALUE;
for (int i = 0; i < 2; i++) drink = Math.min(drink, Integer.parseInt(br.readLine()));
bw.write(String.valueOf(burger + drink - 50));
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub


문제

상근날드에서 가장 잘 팔리는 메뉴는 세트 메뉴이다. 주문할 때, 자신이 원하는 햄버거와 음료를 하나씩 골라, 세트로 구매하면, 가격의 합계에서 50원을 뺀 가격이 세트 메뉴의 가격이 된다.

햄버거는 총 3종류 상덕버거, 중덕버거, 하덕버거가 있고, 음료는 콜라와 사이다 두 종류가 있다.

햄버거와 음료의 가격이 주어졌을 때, 가장 싼 세트 메뉴의 가격을 출력하는 프로그램을 작성하시오.

입력

입력은 총 다섯 줄이다. 첫째 줄에는 상덕버거, 둘째 줄에는 중덕버거, 셋째 줄에는 하덕버거의 가격이 주어진다. 넷째 줄에는 콜라의 가격, 다섯째 줄에는 사이다의 가격이 주어진다. 모든 가격은 100원 이상, 2000원 이하이다.

출력

첫째 줄에 가장 싼 세트 메뉴의 가격을 출력한다.

예제 입력 1 

800
700
900
198
330

예제 출력 1 

848


문제 설명

1. 하이픈으로 나눠진 성(first name)이 존재한다.
2. 성의 첫 번째 글자들만 모아서 출력하면 된다.

풀이

1. StringTokenizer 로 하이픈 기준으로 잘라서 출력

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/2902
* BOJ 백준온라인져지 2902 KMP는 왜 KMP일까? 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), "-");
while (st.hasMoreTokens()) {
bw.write(st.nextToken().charAt(0));
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

KMP 알고리즘이 KMP인 이유는 이를 만든 사람의 성이 Knuth, Morris, Prett이기 때문이다. 이렇게 알고리즘에는 발견한 사람의 성을 따서 이름을 붙이는 경우가 많다.

또 다른 예로, 유명한 비대칭 암호화 알고리즘 RSA는 이를 만든 사람의 이름이 Rivest, Shamir, Adleman이다.

사람들은 이렇게 사람 성이 들어간 알고리즘을 두 가지 형태로 부른다.

  • 첫 번째는 성을 모두 쓰고, 이를 하이픈(-)으로 이어 붙인 것이다. 예를 들면, Knuth-Morris-Pratt이다. 이것을 긴 형태라고 부른다.
  • 두 번째로 짧은 형태는 만든 사람의 성의 첫글자만 따서 부르는 것이다. 예를 들면, KMP이다.

동혁이는 매일매일 자신이 한 일을 모두 메모장에 적어놓는다. 잠을 자기 전에, 오늘 하루 무엇을 했는지 되새겨보는 것으로 하루를 마감한다.

하루는 이 메모를 보던 중, 지금까지 긴 형태와 짧은 형태를 섞어서 적어논 것을 발견했다.

이렇게 긴 형태로 하루 일을 기록하다가는 메모장 가격이 부담되어 파산될 것이 뻔하기 때문에, 앞으로는 짧은 형태로 기록하려고 한다.

긴 형태의 알고리즘 이름이 주어졌을 때, 이를 짧은 형태로 바꾸어 출력하는 프로그램을 작성하시오.

입력

입력은 한 줄로 이루어져 있고, 최대 100글자의 영어 알파벳 대문자, 소문자, 그리고 하이픈 ('-', 아스키코드 45)로만 이루어져 있다. 첫번째 글자는 항상 대문자이다. 그리고, 하이픈 뒤에는 반드시 대문자이다. 그 외의 모든 문자는 모두 소문자이다.

출력

첫 줄에 짧은 형태 이름을 출력한다.

예제 입력 1 

Knuth-Morris-Pratt

예제 출력 1 

KMP


import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/2522
* BOJ 백준온라인져지 2522 별 찍기 - 12 풀이
*/
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int N = Integer.parseInt(br.readLine());
for (int i = 1; i <= N; i++) {
for (int j = N; i < j; j--) bw.write(" ");
for (int j = 0; j < i; j++) bw.write("*");
bw.write("\n");
}
for (int i = 1; i < N; i++) {
for (int j = 0; j < i; j++) bw.write(" ");
for (int j = 1; j <= N - i; j++) bw.write("*");
bw.write("\n");
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub


문제

  예제를 보고 별찍는 규칙을 유추한 뒤에 별을 찍어 보세요.

입력

  첫째 줄에 N (1<=N<=100) 주어진다.

출력

  첫째 줄부터 2*N-1번째  까지 차례대로 별을 출력한다.

예제 입력 1 

3

예제 출력 1 

  *
 **
***
 **
  *

출처


문제 설명

1. Mi 의 숫자가 N 에 존재하는지 출력하는 문제

풀이

1. 이분탐색을 사용하라고 문제 분류가 돼있지만, 더 빠른 풀이를 위해 BitSet 을 사용했다.
2. 이분탐색을 사용하면 O(MlgN + NlgN) 정렬하고 찾는 시간이고, BitSet 을 사용하면(N+M) 이다.
3. 메모리 제한도 높고, Mi 의 제한도 높지 않아서 쉽게 풀 수 있었다.
4. JAVA 로 약 680MS 로 정답이니 거의 엄청 빠른 퍼포먼스를 낼 수 있었다. (첫 제출은 790MS 정도였다. 이유는 숫자 + 문자열을 write 해줬기 때문이다. 변경된 것은 문자열로만 되게)

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/10815
* BOJ 백준온라인져지 10815 숫자 카드 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
BitSet bitSet = new BitSet();
for (int i = 0; i < N; i++) bitSet.set(Integer.parseInt(st.nextToken()) + 10000000);
int M = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
for (int i = 0; i < M; i++) bw.write((bitSet.get(Integer.parseInt(st.nextToken()) + 10000000) ? "1 " : "0 "));
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

숫자 카드는 정수 하나가 적혀져 있는 카드이다. 상근이는 숫자 카드 N개를 가지고 있다. 숫자 M개가 주어졌을 때, 이 숫자가 적혀있는 숫자 카드를 상근이가 가지고 있는지 아닌지를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N (1 ≤ N ≤ 500,000)이가 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 숫자가 주어진다. 숫자 카드에 적혀있는 숫자는 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다. 두 숫자 카드에 같은 숫자가 적혀있는 경우는 없다.

셋째 줄에는 M (1 ≤ M ≤ 500,000)이 주어진다. 넷째 줄에는 상근이가 가지고 있는 숫자 카드인지 아닌지를 구해야 할 M개의 숫자가 주어지며, 이 숫자는 공백으로 구분되어져 있다. 이숫자도 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다

출력

첫째 줄에 입력으로 주어진 M개의 숫자에 대해서, 각 숫자가 적힌 숫자 카드를 상근이가 가지고 있으면 1을, 아니면 0을 공백으로 구분해 출력한다.

예제 입력 1 

5
6 3 2 10 -10
8
10 9 -5 2 3 4 5 -10

예제 출력 1 

1 0 0 1 1 0 0 1

출처


문제 설명

1. 문제에서 제시하는 모양으로 별을 찍으면 된다.
2. 풀고나서 생각난건데 character 배열에 하면 두 삼각형을 겹쳐서 만들고 출력해줘도 됐을 것 같다.

풀이

1. 위의 삼각형은 꼭짓점 하나를 없애고 출력한다.
2. 밑의 삼각형은 꼭짓점이 3 개 다 있는 상태로 출력한다.
3. 위의 삼각형은 (N - i) * 2 + 1 개 별을 출력
4. 밑의 삼각형은 (i - 1)* 2 + 1 개의 별을 출력
5. i 는 시작줄의 개수 1부터 시작

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/2446
* BOJ 백준온라인져지 2446 별찍기 - 9 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
for (int i = 1; i < N; i++) {
for (int j = 1; j < i; j++) bw.write(" ");
for (int j = 0; j < (N - i) * 2 + 1; j++) bw.write("*");
bw.write("\n");
}
for (int i = 0; i < N; i++) {
for (int j = 1; j < N - i; j++) bw.write(" ");
for (int j = 0; j < i * 2 + 1; j++) bw.write("*");
bw.write("\n");
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub


문제

예제를 보고 별찍는 규칙을 유추한 뒤에 별을 찍어 보세요.

입력

첫째 줄에 N (1<=N<=100)이 주어진다.

출력

첫째 줄부터 2*N-1번째 줄 까지 차례대로 별을 출력한다.

예제 입력 1 

5

예제 출력 1 

*********
 *******
  *****
   ***
    *
   ***
  *****
 *******
*********

출처


문제 설명

1. 숫자들의 제곱 합을 10 으로 나눴을 때, 나머지를 출력하면 된다.

풀이

1. Math.pow 라는 메소드를 사용해 제곱연산 (변수로 선언하고 변수 * 변수 했어도 됨)

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/2475
* BOJ 백준온라인져지 2475 검증수 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int sum = 0;
for (int i = 0; i < 5; i++) {
sum += Math.pow(Integer.parseInt(st.nextToken()), 2);
}
bw.write(String.valueOf(sum % 10));
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

컴퓨터를 제조하는 회사인 KOI 전자에서는 제조하는 컴퓨터마다 6자리의 고유번호를 매긴다. 고유번호의 처음 5자리에는 00000부터 99999까지의 수 중 하나가 주어지며 6번째 자리에는 검증수가 들어간다. 검증수는 고유번호의 처음 5자리에 들어가는 5개의 숫자를 각각 제곱한 수의 합을 10으로 나눈 나머지이다.

예를 들어 고유번호의 처음 5자리의 숫자들이 04256이면, 각 숫자를 제곱한 수들의 합 0+16+4+25+36 = 81 을 10으로 나눈 나머지인 1이 검증수이다.

입력

첫째 줄에 고유번호의 처음 5자리의 숫자들이 빈칸을 사이에 두고 하나씩 주어진다.

출력

첫째 줄에 검증수를 출력한다.

예제 입력 1 

0 4 2 5 6

예제 출력 1 

1


문제 설명

1. 알파뱃이 몇 번 나왔는지 출력해주면 됨

풀이

1. 문자열에서 한 문자씩 확인

더 빠른 방법: 문자열로 기록 x -> 문자로 받고 바로바로 연산하면 엄청 빨라질듯 하다. (공간복잡도 O(1))

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/10808
* BOJ 백준온라인져지 10808 알파벳 개수 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
private static int alpha[] = new int[26];
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
for (int i = 0; i < str.length(); i++) {
alpha[str.charAt(i) - 'a']++;
}
for (int i = 0; i < 26; i++) {
bw.write(alpha[i] + " ");
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

알파벳 소문자로만 이루어진 단어 S가 주어진다. 각 알파벳이 단어에 몇 개가 포함되어 있는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 단어 S가 주어진다. 단어의 길이는 100을 넘지 않으며, 알파벳 소문자로만 이루어져 있다.

출력

단어에 포함되어 있는 a의 개수, b의 개수, …, z의 개수를 공백으로 구분해서 출력한다.

예제 입력 1 

baekjoon

예제 출력 1 

1 1 0 0 1 0 0 0 0 1 1 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0


+ Recent posts