https://www.acmicpc.net/problem/1451
1451번: 직사각형으로 나누기
첫째 줄에 직사각형의 세로 크기 N과 가로 크기 M이 주어진다. 둘째 줄부터 직사각형에 들어가는 수가 가장 윗 줄부터 한 줄에 하나씩 M개의 수가 주어진다. N과 M은 50보다 작거나 같은 자연수이
www.acmicpc.net
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static int n, m;
public static int[][] arr;
public static long sum(int ax, int ay, int bx, int by) {
int cnt = 0;
for (int i = ax; i <= bx; i++) {
for (int j = ay; j <= by; j++) {
cnt += arr[i][j];
}
}
return cnt;
}
public static void main(String[] args) throws NumberFormatException, IOException {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
arr = new int[n + 1][m + 1];
for (int i = 0; i < n; i++) {
String s = sc.next();
for (int j = 0; j < m; j++) {
arr[i][j] = s.charAt(j) - '0';
}
}
// 직사각형 나누는 방법 6가지
// case 1
// 꼭짓점,끝과 끝을 sum에 넣어주는 거
long ans = 0;
for (int i = 0; i < m - 2; i++) {// 축1
for (int j = i + 1; j < m - 1; j++) {// 축2
long sum1 = sum(0, 0, n - 1, i);
long sum2 = sum(0, i + 1, n - 1, j);// i+1이 아니라 j 끝과 끝 생각
long sum3 = sum(0, j + 1, n - 1, m - 1);
if (ans < sum1 * sum2 * sum3) {
ans = sum1 * sum2 * sum3;
}
}
}
// case 2
for (int i = 0; i < n - 2; i++) {
for (int j = i + 1; j < n - 1; j++) {
long sum1 = sum(0, 0, i, m - 1);
long sum2 = sum(i + 1, 0, j, m - 1);
long sum3 = sum(j + 1, 0, n - 1, m - 1);
if (ans < sum1 * sum2 * sum3) {
ans = sum1 * sum2 * sum3;
}
}
}
// case 3
for (int i = 0; i < n - 1; i++) {// 행을 가르는 축
for (int j = 0; j < m - 1; j++) {// 열을 가르는 축
long sum1 = sum(0, 0, i, m - 1);
long sum2 = sum(i + 1, 0, n - 1, j);
long sum3 = sum(i + 1, j + 1, n - 1, m - 1);
if (ans < sum1 * sum2 * sum3) {
ans = sum1 * sum2 * sum3;
}
}
}
// case 4
for (int i = 0; i < m - 1; i++) {
for (int j = 0; j < n - 1; j++) {
long sum1 = sum(0, 0, j, i);
long sum2 = sum(0, i + 1, j, m - 1);
long sum3 = sum(j + 1, 0, n - 1, m - 1);
if (ans < sum1 * sum2 * sum3) {
ans = sum1 * sum2 * sum3;
}
}
}
// case 5
for (int i = 0; i < m - 1; i++) {// 열을 가르는
for (int j = 0; j < n - 1; j++) {
long sum1 = sum(0, 0, n - 1, i);
long sum2 = sum(0, i + 1, j, m - 1);
long sum3 = sum(j + 1, i + 1, n - 1, m - 1);
if (ans < sum1 * sum2 * sum3) {
ans = sum1 * sum2 * sum3;
}
}
}
// case 6
for (int i = 0; i < m - 1; i++) {
for (int j = 0; j < n - 1; j++) {
long sum1 = sum(0, 0, j, i);
long sum2 = sum(j + 1, 0, n - 1, i);
long sum3 = sum(0, i + 1, n - 1, m - 1);
if (ans < sum1 * sum2 * sum3) {
ans = sum1 * sum2 * sum3;
}
}
}
System.out.println(ans);
}
}
|
cs |
3개의 직사각형을 나눌 수 있는 방법은 총 6가지이다.
![](https://blog.kakaocdn.net/dn/kI4Q4/btrtsGmjAAI/JSScC479IoqfbYxaWFDklk/img.png)
근데 문제는 이걸 어떻게 나눠주느냐에 있었다. 사실 너무 어려워서 다른 사람의 sum메서드 코드를 보았다.
우선 구획한 직사각형을 더해주는 sum 메서드를 보자.
1
2
3
4
5
6
7
8
9
10
|
public static long sum(int ax, int ay, int bx, int by) {
int cnt = 0;
for (int i = ax; i <= bx; i++) {
for (int j = ay; j <= by; j++) {
cnt += arr[i][j];
}
}
return cnt;
}
|
cs |
직사각형이 시작하는 부분부터 끝나는 부분 즉 끝과 끝의 행과 열의 index를 받아서 더해주는 방법을 생각해보았다.
결국에 직사각형의 꼭짓점들만 받아올 수 있게 코드를 짜면 되겠다는 생각이 들었다.
case 1)
얘의 경우 열을 가르는 축 2개만 필요하다. 두개의 축을 각각 i,j라 둘건데, i는 m-2 전까지 돌 수 있고 (적어도 2칸 남겨야함),j는 m-1 전까지 돌 수 있다.(적어도 뒤에 한칸 남겨야함)
sum함수에는 (시작점 행,시작점 열,끝점 행,끝점 열)을 넣어주면 된다.
case2)
그렇다면 행을 가르는 축을 i로 두고 열을 가르는 축을 j로 두자.
위와 같은 경우를 살펴볼 것이다.
이 모양도 위에랑 똑같이 행을 가르는걸 i축, 열을 가르는걸 j축으로 두면 된다.
아까 case1이랑 달라지는건 i는 m-2가 아니라 m-1 전까지 잘릴 수 있다. 왜냐면 얘는 2등분만 하면 되기 때문에 뒤에 한부분만 남기면 되기 때문이다. j도 m-1 전까지 자를 수 있다.
이해하면 그 다음부턴 코드가 술술 써지는데 처음에 기준잡는게 너무 어렵다....ㅜ
참고 사이트
https://dbstndi6316.tistory.com/116
[백준문제풀이] 1451 직사각형으로 나누기
풀이일시 : 2020-10-15 문제 : 세준이는 N*M크기로 직사각형에 수를 N*M개 써놓았다. 세준이는 이 직사각형을 겹치지 않는 3개의 작은 직사각형으로 나누려고 한다. 각각의 칸은 단 하나의 작은 직
dbstndi6316.tistory.com
https://log-laboratory.tistory.com/128
[백준] 1451번 자바 직사각형으로 나누기
문제 출처 https://www.acmicpc.net/problem/1451 1451번: 직사각형으로 나누기 첫째 줄에 직사각형의 세로 크기 N과 가로 크기 M이 주어진다. 둘째 줄부터 직사각형에 들어가는 수가 가장 윗 줄부터 한 줄에
log-laboratory.tistory.com
'알고리즘 > 완전탐색' 카테고리의 다른 글
[C++ 백준] 실버 5/1436번 영화감독 숌 (0) | 2022.02.21 |
---|---|
[java 백준] 골드 1/ 2098번 외판원 순회 2 (0) | 2022.02.20 |
[java 백준] 골드 5/1107번 리모컨 (0) | 2022.02.13 |
[C++백준] 실버 2/ 10819번 차이를 최대로 (0) | 2022.02.09 |
[java 백준] 실버 5/ 1476번 날짜계산 (0) | 2021.08.30 |
댓글