일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 시간 복잡도
- 백준단계별로풀어보기
- 무료코딩강의
- 다이나믹 프로그래밍
- Java개념
- dfs
- 동적계획법
- 백트래킹
- 알고리즘
- 무료개발강의
- 백준
- 백준알고리즘
- 빅오 표기법
- dp
- 자바의정석연습문제
- 브루트포스
- 알고리즘공부
- 자바개념
- 코딩공부
- 백준9단계
- ★
- 자바공부
- ☆
- 개발공부
- java
- 백준자바
- 자바의정석연습문제풀이
- BFS
- 자바
- 자바의정석
- Today
- Total
더 많이 실패하기
공부 179-180일차: 백준 14391번 종이 조각 자바 java 본문
14391 종이 조각
https://www.acmicpc.net/problem/14391
14391번: 종이 조각
영선이는 숫자가 쓰여 있는 직사각형 종이를 가지고 있다. 종이는 1×1 크기의 정사각형 칸으로 나누어져 있고, 숫자는 각 칸에 하나씩 쓰여 있다. 행은 위에서부터 아래까지 번호가 매겨져 있고,
www.acmicpc.net
백준 14391번 문제 종이 조각
문제
시간 제한 | 메모리 제한 | 제출 | 정답 | 맞힌 사람 | 정답 비율 |
---|---|---|---|---|---|
2 초 | 512 MB | 5436 | 2972 | 2201 | 55.820% |
문제
영선이는 숫자가 쓰여 있는 직사각형 종이를 가지고 있다. 종이는 1×1 크기의 정사각형 칸으로 나누어져 있고, 숫자는 각 칸에 하나씩 쓰여 있다. 행은 위에서부터 아래까지 번호가 매겨져 있고, 열은 왼쪽부터 오른쪽까지 번호가 매겨져 있다.
영선이는 직사각형을 겹치지 않는 조각으로 자르려고 한다. 각 조각은 크기가 세로나 가로 크기가 1인 직사각형 모양이다. 길이가 N인 조각은 N자리 수로 나타낼 수 있다. 가로 조각은 왼쪽부터 오른쪽까지 수를 이어 붙인 것이고, 세로 조각은 위에서부터 아래까지 수를 이어붙인 것이다.
아래 그림은 4×4 크기의 종이를 자른 한 가지 방법이다.

각 조각의 합은 493 + 7160 + 23 + 58 + 9 + 45 + 91 = 7879 이다.
종이를 적절히 잘라서 조각의 합을 최대로 하는 프로그램을 작성하시오.
입력
첫째 줄에 종이 조각의 세로 크기 N과 가로 크기 M이 주어진다. (1 ≤ N, M ≤ 4)
둘째 줄부터 종이 조각이 주어진다. 각 칸에 쓰여 있는 숫자는 0부터 9까지 중 하나이다.
출력
영선이가 얻을 수 있는 점수의 최댓값을 출력한다.
예제 입력 1
2 3
123
312
예제 출력 1
435
예제 입력 2
2 2
99
11
예제 출력 2
182
예제 입력 3
4 3
001
010
111
100
예제 출력 3
1131
예제 입력 4
1 1
8
예제 출력 4
8
과정 생각해보기 & 오답
핵심 생각은 아래와 같다

가로와 세로를 각각 0, 1로 구분하는 것이다
(다만 비트마스킹 연산이 아직 생소하기 때문에 boolean값으로 설정하여 문제를 풀 것이다)
이후 이 블로그를 참고했다
이 방법은 재귀를 이용한 방법이고, 비트마스킹으로도 풀 수 있다
실제 백준 사이트는 이 문제를 비트마스킹 카테고리로 나누기도 했다
사실 이 방법도 가로 true, 세로 false로 설정하여 푸는 것은 같으므로, 단순하게 생각하면 booelan 값 대신 0과 1을 넣으면 비트마스킹 풀이가 된다(다만 연산 표현 방법이 달라서 매우 생소하게 느껴진다)
이 블로그에 재귀, 비트마스킹 풀이가 모두 담겨있으니 참고하면 좋을 듯하다
https://gimbalja.tistory.com/326
비트마스킹
비트마스킹(bit masking) 컴퓨터의 최소 단위 bit는 binary digit의 약자로, 이진수를 뜻한다. 1은 비트가 켜져있다, 0은 비트가 꺼져있다고도 표현한다. 비트 연산자
gimbalja.tistory.com
여기에 비트마스킹 개념을 보기 쉽게 정리하고 있다
정답 인정 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
import java.io.*;
import java.util.*;
public class Main {
static int n, m;
static int max = Integer.MIN_VALUE;
static int[][] paper;
static boolean[][] visited;
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());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
paper = new int[n][m];
visited = new boolean[n][m];
for(int i = 0; i < n; i++) {
String str = br.readLine();
for(int j = 0; j < m; j++) {
paper[i][j] = str.charAt(j)-'0';
}
}
// System.out.println(Arrays.deepToString(paper));
DFS(0, 0);
bw.write(max+"");
bw.flush();
bw.close();
}
static void DFS(int depth, int width){
// System.out.println(Arrays.deepToString(visited));
if(depth == n) { // 모든 깊이(세로) 탐색 완료->최댓값 출력
getMax();
return;
}
if(width == m) { // 한 줄 다 확인했으면
DFS(depth+1, 0); // 다음행 1열로
return;
}
// 가로
visited[depth][width] = false; // 0 표시
DFS(depth, width+1);
// 세로
visited[depth][width] = true; // 1 표시
DFS(depth, width+1);
}
static void getMax() {
int num = 0;
int temp = 0;
// 가로
for(int i = 0; i < n; i++) {
temp = 0;
for(int j = 0; j < m; j++) {
if(!visited[i][j]) { // 0 -> 가로
temp *= 10; // 더해질 때마다 자릿수 늘려주기
temp += paper[i][j];
}else {
num += temp;
temp = 0; // 세로니까 초기화
}
}
num += temp;
}
// 세로
for(int i = 0; i < m; i++) {
temp = 0;
for(int j = 0; j < n; j++) {
if(visited[j][i]) { // 1 -> 세로
temp *= 10; // 더해질 때마다 자릿수 늘려주기
temp += paper[j][i];
}else {
num += temp;
temp = 0; // 가로니까 초기화
}
}
num += temp;
}
max = Math.max(num, max);
// System.out.println("max : "+max);
}
}
|
cs |
2) 비트마스킹
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
import java.io.*;
import java.util.*;
public class Main {
static int n, m;
static int max = Integer.MIN_VALUE;
static int[][] paper;
static boolean[][] visited;
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());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
paper = new int[n][m];
visited = new boolean[n][m];
for(int i = 0; i < n; i++) {
String str = br.readLine();
for(int j = 0; j < m; j++) {
paper[i][j] = str.charAt(j)-'0';
}
}
getMax();
bw.write(max+"");
bw.flush();
bw.close();
}
static void getMax() {
// 2^n*m
for(int t = 0; t < (1<<(n*m)); t++) {
int num = 0;
// 0 -> 가로
for(int i = 0; i < n; i++) {
int temp = 0;
for(int j = 0; j < m; j++) {
if((t&(1<<(i*m+j))) == 0) { // 해당 자리의 비트가 꺼져있다면 == 0이라면 == 가로라면
temp *= 10; // 더해질 때마다 자릿수 늘려주기
temp += paper[i][j];
}else {
num += temp;
temp = 0; // 세로니까 초기화
}
}
num += temp;
}
// 1 -> 세로
for(int i = 0; i < m; i++) {
int temp = 0;
for(int j = 0; j < n; j++) {
if((t&(1<<j*m+i)) != 0) { // 해당 자리의 비트가 켜있다면 == 1이라면 == 세로라면
temp *= 10; // 더해질 때마다 자릿수 늘려주기
temp += paper[j][i];
}else {
num += temp;
temp = 0; // 가로니까 초기화
}
}
num += temp;
}
max = Math.max(num, max);
}
}
}
|
cs |
갈수록 어려운 건 착각인가..........^^
내일 이 문제 한 번 더 살펴봐야겠다 (완료!)
'알고리즘 > 백준' 카테고리의 다른 글
공부 182일차: 백준 13023번 ABCDE 자바 java (0) | 2023.01.28 |
---|---|
공부 181일차: 백준 1260번 DFS와 BFS 자바 java (0) | 2023.01.27 |
공부 178일차: 백준 1182번 부분수열의 합 자바 java (0) | 2023.01.24 |
공부 177일차: 백준 11723번 집합 자바 java (0) | 2023.01.23 |
공부 176일차: 백준 1248번 Guess 자바 java (문제 해설) (0) | 2023.01.22 |