문제 설명

나눠진 영역의 최대 개수를 구하면 된다.
높이는 1 ~ x 까지 다 해보거나 나름대로의 규칙을 찾으면 됨

풀이

나는 다 해보기로 생각했다.
dfs 를 이용해 인접한곳을 다 지워나갔고 dfs 를 실행할 수 있다면 카운트 업 해줬다.
숫자는 다 해볼 필요가 없으므로 1 ~ 나온 숫자중 가장 큰 숫자
까지 했다.

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/2468
* BOJ 백준온라인져지 2468 안전 영역 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
private static int tempMap[][];
private static boolean visited[][];
private static int N;
private static int z;
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
int map[][] = new int[N][N];
int max = 1;
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
max = Math.max(max, map[i][j] = Integer.parseInt(st.nextToken()));
}
}
int result = 1;
for (z = 1; z <= max; z++) {
tempMap = new int[N][N];
visited = new boolean[N][N];
int tempResult = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
tempMap[i][j] = map[i][j];
if (tempMap[i][j] <= z) visited[i][j] = true;
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (!visited[i][j] && tempMap[i][j] > z) {
tempResult++;
dfs(i, j);
}
}
}
result = Math.max(result, tempResult);
}
bw.write(String.valueOf(result));
bw.flush();
}
private static int xxxx[] = { -1, 0, 1, 0 };
private static int yyyy[] = { 0, 1, 0, -1 };
private static void dfs (int x, int y) {
visited[x][y] = true;
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 >= N || visited[curX][curY]) continue;
dfs(curX, curY);
}
}
}
view raw Main.java hosted with ❤ by GitHub

문제

재난방재청에서는 많은 비가 내리는 장마철에 대비해서 다음과 같은 일을 계획하고 있다. 먼저 어떤 지역의 높이 정보를 파악한다. 그 다음에 그 지역에 많은 비가 내렸을 때 물에 잠기지 않는 안전한 영역이 최대로 몇 개가 만들어 지는 지를 조사하려고 한다. 이 때, 문제를 간단하게 하기 위하여, 장마철에 내리는 비의 양에 따라 일정한 높이 이하의 모든 지점은 물에 잠긴다고 가정한다.

어떤 지역의 높이 정보는 행과 열의 크기가 각각 N인 2차원 배열 형태로 주어지며 배열의 각 원소는 해당 지점의 높이를 표시하는 자연수이다. 예를 들어, 다음은 N=5인 지역의 높이 정보이다.

이제 위와 같은 지역에 많은 비가 내려서 높이가 4 이하인 모든 지점이 물에 잠겼다고 하자. 이 경우에 물에 잠기는 지점을 회색으로 표시하면 다음과 같다. 

물에 잠기지 않는 안전한 영역이라 함은 물에 잠기지 않는 지점들이 위, 아래, 오른쪽 혹은 왼쪽으로 인접해 있으며 그 크기가 최대인 영역을 말한다. 위의 경우에서 물에 잠기지 않는 안전한 영역은 5개가 된다(꼭지점으로만 붙어 있는 두 지점은 인접하지 않는다고 취급한다). 

또한 위와 같은 지역에서 높이가 6이하인 지점을 모두 잠기게 만드는 많은 비가 내리면 물에 잠기지 않는 안전한 영역은 아래 그림에서와 같이 네 개가 됨을 확인할 수 있다. 

이와 같이 장마철에 내리는 비의 양에 따라서 물에 잠기지 않는 안전한 영역의 개수는 다르게 된다. 위의 예와 같은 지역에서 내리는 비의 양에 따른 모든 경우를 다 조사해 보면 물에 잠기지 않는 안전한 영역의 개수 중에서 최대인 경우는 5임을 알 수 있다. 

어떤 지역의 높이 정보가 주어졌을 때, 장마철에 물에 잠기지 않는 안전한 영역의 최대 개수를 계산하는 프로그램을 작성하시오. 

입력

첫째 줄에는 어떤 지역을 나타내는 2차원 배열의 행과 열의 개수를 나타내는 수 N이 입력된다. N은 2 이상 100 이하의 정수이다. 둘째 줄부터 N 개의 각 줄에는 2차원 배열의 첫 번째 행부터 N번째 행까지 순서대로 한 행씩 높이 정보가 입력된다. 각 줄에는 각 행의 첫 번째 열부터 N번째 열까지 N 개의 높이 정보를 나타내는 자연수가 빈 칸을 사이에 두고 입력된다. 높이는 1이상 100 이하의 정수이다. 

출력

첫째 줄에 장마철에 물에 잠기지 않는 안전한 영역의 최대 개수를 출력한다. 

예제 입력 1 

5
6 8 2 6 2
3 2 3 4 6
6 7 3 3 2
7 2 5 3 6
8 9 5 2 7

예제 출력 1 

5


문제 설명

A 의 수열이 있을 때, |Ai - Ai+1| ~ |An-2 - An-1| 의 합 중 최대값을 구하면 된다.

풀이

완전 탐색으로 다 확인했다.
1. O(N!) 이여서 그렇게 오래 걸리지도 않는다.
사용한지 안한지는 비트마스크를 이용해서 했다.

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/10819
* BOJ 백준온라인져지 10819 차이를 최대로 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
private static int arr[] = new int[8];
private static int N;
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
int max = 0;
for (int i = 0; i < N; i++) {
max = Math.max(max, bruteforce(1 << i, arr[i]));
}
bw.write(String.valueOf(max));
bw.flush();
}
private static int bruteforce (int check, int cur) {
int max = 0;
for (int i = 0; i < N; i++) {
if (((1 << i) & check) > 0) continue;
max = Math.max(max, bruteforce(check | (1 << i), arr[i]) + Math.abs(cur - arr[i]));
}
return max;
}
}
view raw Main.java hosted with ❤ by GitHub
시간 제한메모리 제한제출정답맞은 사람정답 비율
1 초256 MB47832862226761.303%

문제

N개의 정수로 이루어진 배열 A가 주어진다. 이 때, 배열에 들어있는 정수의 순서를 적절히 바꿔서 다음 식의 최대값을 구하는 프로그램을 작성하시오.

|A[0] - A[1]| + |A[1] - A[2]| + ... + |A[N-2] - A[N-1]|

입력

첫째 줄에 N (3 ≤ N ≤ 8)이 주어진다. 둘째 줄에는 배열 A에 들어있는 정수가 주어진다. 배열에 들어있는 정수는 -100보다 크거나 같고, 100보다 작거나 같다.

출력

첫째 줄에 배열에 들어있는 수의 순서를 적절히 바꿔서 얻을 수 있는 식의 최댓값을 출력한다.

예제 입력 1 

6
20 1 15 8 4 10

예제 출력 1 

62

출처


문제 설명

1. Connected Component 의 개수를 구하면 된다.
즉 연결되있는 Vertex 끼리 그룹화 시켜서 그룹의 개수를 구하면 됨.

풀이

BFS 를 사용해도 풀 수 있지만, 더 많은 코드가 필요할 것 같아서 dfs 를 사용해서 풀었다.
well-known 문제이기 때문에 설명은 필요없을 것 같다.
1. visited, edges 를 이용해서 품

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/11724
* BOJ 백준온라인져지 11724 연결 요소의 개수 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
private static int N, M;
private static boolean visited[], edges[][];
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());
edges = new boolean[N + 1][N + 1];
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int s = Integer.parseInt(st.nextToken());
int e = Integer.parseInt(st.nextToken());
edges[s][e] = edges[e][s] = true;
}
visited = new boolean[N + 1];
int result = 0;
for (int i = 1; i <= N; i++) {
if (!visited[i]) {
result++;
dfs(i);
}
}
bw.write(String.valueOf(result));
bw.flush();
}
private static void dfs (int x) {
visited[x] = true;
for (int i = 1; i <= N; i++) {
if (!edges[x][i] || visited[i]) continue;
dfs(i);
}
}
}
view raw Main.java hosted with ❤ by GitHub

문제

방향 없는 그래프가 주어졌을 때, 연결 요소 (Connected Component)의 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. (1 ≤ N ≤ 1,000, 0 ≤ M ≤ N×(N-1)/2) 둘째 줄부터 M개의 줄에 간선의 양 끝점 u와 v가 주어진다. (1 ≤ u, v ≤ N, u ≠ v) 같은 간선은 한 번만 주어진다.

출력

첫째 줄에 연결 요소의 개수를 출력한다.

예제 입력 1 

6 5
1 2
2 5
5 1
3 4
4 6

예제 출력 1 

2

예제 입력 2 

6 8
1 2
2 5
5 1
3 4
4 6
5 4
2 4
2 3

예제 출력 2 

1

출처


문제 설명

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


문제 설명

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????


문제 설명

1. 연산자 우선순위는 없고 순서대로 연산하는거다. (앞에서부터)
2. 잘 배치해서 최대값, 최소값을 구해주면 된다.

풀이

1. dfs (브루트포스) 를 사용해서 완전 탐색을 해본다.
2. 모든 경우의 수를 대입하게 되면 무조건 답을 구할 수 밖에 없다.

코드

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/14888
* BOJ 백준온라인져지 14888 연산자 끼워넣기 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
private static int arr[];
private static int operators[] = new int[4];
private static int max = Integer.MIN_VALUE;
private static int min = Integer.MAX_VALUE;
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
arr = new int[N];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) arr[i] = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
for (int i = 0; i < 4; i++) operators[i] = Integer.parseInt(st.nextToken());
dfs(arr[0], 1);
bw.write(String.valueOf(max));
bw.write("\n");
bw.write(String.valueOf(min));
bw.flush();
}
private static void dfs (int sum, int idx) {
if (idx == arr.length) {
max = Math.max(sum, max);
min = Math.min(sum, min);
}
for (int i = 0; i < 4; i++) {
if (operators[i] > 0) {
operators[i]--;
switch (i) {
case 0: dfs(sum + arr[idx], idx + 1); break;
case 1: dfs(sum - arr[idx], idx + 1); break;
case 2: dfs(sum * arr[idx], idx + 1); break;
case 3: dfs(sum / arr[idx], idx + 1); break;
}
operators[i]++;
}
}
}
}
view raw Main.java hosted with ❤ by GitHub

문제

N개의 수로 이루어진 수열 A1, A2, ..., AN이 주어진다. 또, 수와 수 사이에 끼워넣을 수 있는 N-1개의 연산자가 주어진다. 연산자는 덧셈(+), 뺄셈(-), 곱셈(×), 나눗셈(÷)로만 이루어져 있다.

우리는 수와 수 사이에 연산자를 하나씩 넣어서, 수식을 하나 만들 수 있다. 이 때, 주어진 수의 순서를 바꾸면 안된다.

예를 들어, 6개의 수로 이루어진 수열이 1, 2, 3, 4, 5, 6이고, 주어진 연산자가 덧셈(+) 2개, 뺄셈(-) 1개, 곱셈(×) 1개, 나눗셈(÷) 1개인 경우에는 총 60가지의 식을 만들 수 있다. 예를 들어, 아래와 같은 식을 만들 수 있다.

  • 1+2+3-4×5÷6
  • 1÷2+3+4-5×6
  • 1+2÷3×4-5+6
  • 1÷2×3-4+5+6

식의 계산은 연산자 우선 순위를 무시하고 앞에서부터 진행해야 한다. 또, 나눗셈은 정수 나눗셈으로 몫만 취한다. 음수를 양수로 나눌 때는 C++14의 기준을 따른다. 즉 양수로 바꾼 뒤 몫을 취하고, 그 몫을 음수로 바꾼 것과 같다. 이에 따라서, 위의 식 4개의 결과를 계산해보면 아래와 같다.

  • 1+2+3-4×5÷6 = 1
  • 1÷2+3+4-5×6 = 12
  • 1+2÷3×4-5+6 = 5
  • 1÷2×3-4+5+6 = 7

N개의 수와 N-1개의 연산자가 주어졌을 때, 만들 수 있는 식의 결과가 최대인 것과 최소인 것을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 곱셈(×)의 개수, 나눗셈(÷)의 개수이다. 

출력

첫째 줄에 만들 수 있는 식의 결과의 최대값을, 둘째 줄에는 최소값을 출력한다. 최대값과 최소값은 항상 -10억보다 크거나 같고, 10억보다 작거나 같은 결과가 나오는 입력만 주어진다. 또한, 앞에서 부터 계산했을 때, 중간에 계산되는 식의 결과도 항상 -10억보다 크거나 같고, 10억보다 작거나 같다.

예제 입력 1 

2
5 6
0 0 1 0

예제 출력 1 

30
30

예제 입력 2 

3
3 4 5
1 0 1 0

예제 출력 2 

35
17

예제 입력 3 

6
1 2 3 4 5 6
2 1 1 1

예제 출력 3 

54
-24

힌트

세 번째 예제의 경우에 다음과 같은 식이 최대값/최소값이 나온다.

  • 최대값: 1-2÷3+4+5×6
  • 최소값: 1+2+3÷4-5×6


1. O(N^3) 인 문제

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/10163
* BOJ 백준온라인져지 10163 색종이 풀이
*/
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());
int map[][] = new int[101][101];
for (int i = 1; i <= N; i++) {
StringTokenizer 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 < x1 + x2; j++) {
for (int k = y1; k < y1 + y2; k++) {
map[j][k] = i;
}
}
}
for (int z = 1; z <= N; z++) {
int cnt = 0;
for (int i = 0; i < 101; i++) {
for (int j = 0; j < 101; j++) {
if (map[i][j] == z) cnt++;
}
}
bw.write(cnt + "\n");
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

평면에 색깔이 서로 다른 직사각형 모양의 색종이 N장이 하나씩 차례로 놓여진다. 이 때 색종이가 비스듬하게 놓이는 경우는 없다. 즉, 모든 색종이의 변은 서로 평행하거나, 서로 수직이거나 둘 중 하나이다. 그림-1은 1번, 2번, 3번 세 장의 색종이가 순서대로 놓인 상태를 보여준다.

그림-1

여기에 그림-2에서 보인 것처럼 4번 색종이가 하나 더 놓이면 3번 색종이는 완전히 가려서 보이지 않게 된다. 그리고, 1번 색종이와 2번 색종이는 부분적으로 가려 보이며, 4번 색종이는 완전히 보이게 된다.

그림-2

N장의 색종이가 주어진 위치에 차례로 놓일 경우, 각 색종이가 보이는 부분의 면적을 구하는 프로그램을 작성하시오. 

입력

입력의 첫 번째 줄에는 색종이의 장수를 나타내는 정수 N (1 ≤ N ≤ 100)이 주어진다. 이어서 N장의 색종이에 관한 입력이 각 색종이마다 한 줄씩 차례로 주어진다. 색종이가 놓이는 평면은 가로 최대 101칸, 세로 최대 101칸으로 구성된 격자 모양이다. 격자의 각 칸은 가로, 세로 길이가 1인 면적이 1인 정사각형이다. 

편의상 가로 6칸, 세로 6칸으로 이루어진 격자의 예를 들어 설명하면, 각 칸에 표시된 값 (a,b)는 해당 칸의 번호를 나타낸다. 가장 왼쪽 아래의 칸은 (0,0) 가장 오른 쪽 위의 칸은 (5,5)이다. 

색종이가 놓인 상태는 가장 왼쪽 아래 칸의 번호와 너비, 높이를 나타내는 네 정수로 표현한다. 예를 들어, 위 그림에서 회색으로 표시된 색종이는 (1,4)가 가장 왼쪽 아래에 있고 너비 3, 높이 2이므로 1 4 3 2로 표현한다. 색종이가 격자 경계 밖으로 나가는 경우는 없다. 

출력

입력에서 주어진 순서에 따라 N장의 색종이를 평면에 놓았을 때, 입력에서 주어진 순서대로 각 색종이가 보이는 부분의 면적을 한 줄에 하나씩 하나의 정수로 출력한다. 만약 색종이가 보이지 않는다면 정수 0을 출력한다. 

예제 입력 1 

2
0 0 10 10
2 2 6 6

예제 출력 1 

64
36


1. 좌, 우로만 이동 가능

2. K = 0 인 경우가 있어서 split 할 때 에러가 난다. (try catch 로 해결)

3. 모든 경우를 다 확인한다고 했을 때, O(N)

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/13700
* BOJ 백준온라인져지 13700 완전 범죄 풀이
*/
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));
// N, S, D, F, B, K
String str1[] = br.readLine().split(" ");
int N = Integer.parseInt(str1[0]);
int S = Integer.parseInt(str1[1]) - 1;
int D = Integer.parseInt(str1[2]) - 1;
int F = Integer.parseInt(str1[3]);
int B = Integer.parseInt(str1[4]);
int K = Integer.parseInt(str1[5]);
int map[] = new int[N];
try {
String str2[] = br.readLine().split(" ");
for (int i = 0; i < K; i++) map[Integer.parseInt(str2[i]) - 1] = 1;
} catch (Exception e) {}
Queue<Integer> q = new LinkedList<>();
int step[] = new int[N];
for (int i = 0; i < N; i++) step[i] = -1;
step[S] = 0;
q.offer(S);
while (!q.isEmpty()) {
int x = q.poll();
int l = x - B;
int r = x + F;
if (x == D) {
System.out.println(step[x]);
return;
}
if (l >= 0 && map[l] == 0 && step[l] == -1) {
step[l] = step[x] + 1;
q.offer(l);
}
if (r < N && map[r] == 0 && step[r] == -1) {
step[r] = step[x] + 1;
q.offer(r);
}
}
bw.write("BUG FOUND");
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

홍익대학교 근처에 있는 오락실에 새로운 게임이 들어왔다. 이 게임을 클리어하려면 방금 막 금은방을 턴 마포구 대도 X가 되어 아무에게도 들키지 않고 X의 집에 무사히 도착해야 한다. 게임은 오직 좌우 버튼 두 개로만 진행되고 규칙은 아래와 같다.

  1. 마포구의 모든 건물은 일렬로 나열되어 있고 각 건물에는 1번부터 N번까지 번호가 지정되어 있다. 마포구에는 K개의 경찰서가 있고 경찰 내부에는 이미 X의 얼굴이 알려졌다.
  2. 게임이 시작될 때 X는 막 범행을 끝내고 금은방 S에 있다.
  3. X는 자신의 집 D에 마포구를 떠날 수 있는 비밀 통로를 만들어놓았다. 따라서 경찰에게 발각되지 않고 무사히 집으로 돌아가야 한다.
  4. 좌(←) 버튼을 누르면 후방으로, 우(→) 버튼을 누르면 전방으로 이동한다. X는 마포구 내에서만 이동할 수 있으며, 자신이 오랜 연구 끝에 알아낸 이동 방식을 맹신하여 오직 그 방식으로만 이동한다.
  5. X의 달리기는 매우 빨라서 전방으로 F개의 건물, 후방으로 B개의 건물을 얼굴이 보이지 않는 빠르기로 달릴 수 있다. 하지만 자신도 주체할 수 없을 만큼 빨라서 중간에 멈출 수 없으며, 한 번 달리면 너무 힘들어 10초 동안 건물 앞에서 휴식을 취해야 한다.
  6. X가 경찰서 앞에서 휴식을 취할 경우 그는 집에 돌아가지 못하고 체포된다.

이 게임은 아직 베타 버전이라 무사히 집으로 가는 방법이 없는 버그도 존재한다.

지언이의 취미는 오락실 게임을 누구보다 빠르게 클리어하는 것이다. 그래서 대도 X가 무사히 집에 도착할 수 있는 여러 방법 중에서도 좌우 버튼을 가장 최소로 눌렀을 때의 횟수를 알고 싶다.

마포구 건물의 개수 N, 털린 금은방 S, 빈집털이범의 집 D, 앞으로 한 번에 달릴 수 있는 건물 수 F, 뒤로 한 번에 달릴 수 있는 건물 수 B, 마포구 경찰서의 개수 K, 각 경찰서의 건물 번호 l1, l2, …, lK가 주어질 때 대도 X가 무사히 집에 도착하기 위해 버튼을 눌러야 하는 최소 횟수를 출력하는 프로그램을 작성해라.

만약 집으로 가는 방법이 없는 경우를 발견했다면 이 데이터를 게임 회사에 알리기 위해 “BUG FOUND”를 출력한다.

입력

첫째 줄에 N, S, D, F, B, K가 주어지고, K > 0인 경우에는 둘째 줄에 경찰서의 위치 l1, l2, …, lK가 주어진다. (1 ≤ S, D, k ≤ N ≤ 100000, 0 ≤ F, B ≤ 100000, 0 ≤ K ≤ N/2, S ≠ D ≠ l) 

출력

첫째 줄에 대도 X가 건물 S에서 자신의 집 D로 무사히 가기 위해 지언이가 버튼을 눌러야 하는 최소 횟수를 출력한다. 만약, D에 도달할 수 없는 데이터인 경우 “BUG FOUND”를 출력한다.

예제 입력 1 

20 1 20 2 1 4
5 10 15 19

예제 출력 1 

14

예제 입력 2 

20 1 20 2 1 3
5 6 9

예제 출력 2 

BUG FOUND


1. 1만 이하의 완전수는 4개 뿐이다.

2. 과잉수와 부족수를 구하면 된다.

3. 시간을 줄이려면 소수들을 구해서 뭔가 하면 될 것 같은데, 굳이 그럴 필요가 없다. (1 <= T < 1000)

4. 그래서 하나씩 다 구했다.

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/14563
* BOJ 백준온라인져지 14563 완전수 풀이
*/
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[] = br.readLine().split(" ");
for (int i = 0; i < N; i++) {
int n = Integer.parseInt(str1[i]);
switch (n) {
case 6:
case 28:
case 496:
case 8128:
bw.write("Perfect\n");
break;
default:
int r = 0;
for (int j = 1; j <= n / 2; j++) {
if (n % j == 0) r += j;
}
if (r < n) bw.write("Deficient\n");
else bw.write("Abundant\n");
break;
}
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

어떠한 자연수 N에 대해서 N을 제외한 약수(진약수)의 합이 N이 되는 자연수를 완전수라고 한다. 예를 들어, 6의 약수는 1, 2, 3, 6인데 1+2+3은 6이기 때문에 완전수이다. 또 진약수의 합이 자기 자신보다 작은 경우를 부족수, 진약수의 합이 자기 자신보다 큰 경우를 과잉수라고 한다.

이 때, 어떤 수가 주어질 때 이 수가 완전수인지, 부족수인지, 과잉수인지를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 자연수의 개수 T가 주어진다. T은 1000보다 작은 수이다.

둘째 줄에는 공백을 사이에 두고 완전수인지 구해야 되는 자연수 N이 주어진다.(N<10000)

출력

T개 줄에 걸쳐서 각 자연수에 대해서 완전수면 ‘Perfect’, 부족수면 ‘Deficient’, 과잉수면 ‘Abundant’를 출력한다.

예제 입력 1 

3
28 21 36

예제 출력 1 

Perfect
Deficient
Abundant

힌트

28의 경우 약수가 1, 2, 4, 7, 14, 28 이고, 1+2+4+7+14=28이기 때문에 완전수이다.

21의 경우 약수가 1, 3, 7, 21 이고, 1+3+7=11<21이기 때문에 부족수이다.

36의 경우 약수가 1, 2, 3, 4, 6, 9, 12, 18, 36 이고, 1+2+3+4+6+9+12+18=55>36이기 때문에 과잉수 이다.


1. 예선 문제라 N 도 낮다.

2. 그래서 완전 탐색 함

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/5533
* BOJ 백준온라인져지 5533 유니크 풀이
*/
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());
int grades[][] = new int[N][3];
for (int i = 0; i < N; i++) {
String str1[] = br.readLine().split(" ");
for (int j = 0; j < 3; j++) grades[i][j] = Integer.parseInt(str1[j]);
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < 3; j++) {
boolean isFound = false;
for (int k = 0; k < N; k++) {
if (i == k) continue;
if (grades[i][j] == grades[k][j]) {
grades[k][j] = 0;
isFound = true;
}
}
if (isFound) grades[i][j] = 0;
}
bw.write((grades[i][0] + grades[i][1] + grades[i][2]) + "\n");
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

상근이와 친구들은 MT에 가서 아래 설명과 같이 재미있는 게임을 할 것이다.

각 플레이어는 1이상 100 이하의 정수를 카드에 적어 제출한다. 각 플레이어는 자신과 같은 수를 쓴 사람이 없다면, 자신이 쓴 수와 같은 점수를 얻는다. 만약, 같은 수를 쓴 다른 사람이 있는 경우에는 점수를 얻을 수 없다.

상근이와 친구들은 이 게임을 3번 했다. 각 플레이어가 각각 쓴 수가 주어졌을 때, 3번 게임에서 얻은 총 점수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 참가자의 수 N이 주어진다. (2 ≤ N ≤ 200) 둘째 줄부터 N개 줄에는 각 플레이어가 1번째, 2번째, 3번째 게임에서 쓴 수가 공백으로 구분되어 주어진다.

출력

각 플레이어가 3번의 게임에서 얻은 총 점수를 입력으로 주어진 순서대로 출력한다.

예제 입력 1 

5
100 99 98
100 97 92
63 89 63
99 99 99
89 97 98

예제 출력 1 

0
92
215
198
89

힌트

플레이어 1 : 0 + 0 + 0 = 0

플레이어 2 : 0 + 0 + 92 = 92

플레이어 3 : 63 + 89 + 63 = 215

플레이어 4 : 99 + 0 + 99 = 198

플레이어 5 : 89 + 0 + 0 = 89


+ Recent posts