DY N DY
실력키우기 색종이(고)(C++) 본문
1124 : 색종이(고)
제한시간: 1000 ms 메모리제한: 32 MB
해결횟수: 390 회 시도횟수: 1418 회
가로, 세로의 크기가 각각 100인 정사각형 모양의 흰색 도화지가 있다. 이 도화지 위에 가로, 세로의 크기가 각각 10인 정사각형 모양의 검은색 색종이를 색종이의 변과 도화지의 변이 평행하도록 붙인다. 이러한 방식으로 색종이를 한 장 또는 여러 장 붙인 후 도화지에서 검은색 직사각형을 잘라내려고 한다. 직사각형 또한 그 변이 도화지의 변과 평행하도록 잘라내어야 한다.
예를 들어 흰색 도화지 위에 세 장의 검은색 색종이를 <그림 1>과 같은 모양으로 붙였다. <그림 1>에 표시된 대로 검은색 직사각형을 잘라내면 그 넓이는 22×5=110이 된다.
반면 <그림 2>에 표시된 대로 검은색 직사각형을 잘라내면 그 넓이는 8×15=120이 된다.
검은색 색종이의 수와 각 색종이를 붙인 위치가 주어질 때 잘라낼 수 있는 검은색 직사각형의 최대 넓이를 구하는 프로그램을 작성하시오.
*주의. 직사각형은 정사각형을 포함한다.
[Copy]3 3 7 15 7 5 2 | [Copy]120 |
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 | /************************************************************** Problem: 1124 User: a132034 Language: C++ Result: Success Time:2 ms Memory:1140 kb ****************************************************************/ #include <cstdio> #pragma warning(disable:4996) int paper[111][111]; int H[111]; int main() { int max = 1; int N; scanf("%d", &N); for (int i = 1; i <= N; ++i) { int x, y; scanf("%d%d", &x, &y); for (int a = x; a < x + 10; ++a) for (int b = y; b < y + 10; ++b) paper[a][b] = 1; } for (int i = 2; i <= 100; ++i) { for (int j = 2; j <= 100; ++j) { if (paper[i][j] == 1) paper[i][j] += paper[i][j - 1]; } } for (int i = 1; i <= 100; ++i) { for (int j = 1; j <= 100; ++j) { if (paper[i][j] != 0) { int width = 0; int height = 1; for (int k = 1; k <= 100; ++k) H[k] = 0; for (int k = j - paper[i][j] + 1; k <= j; ++k) { H[k] = paper[i][k]; if (H[k] > 0) width++; } bool flg = true; for (int h = i - 1; h > 0; --h) { for (int k = j - paper[i][j] + 1; k <= j; ++k) { if (H[k] > 0 && paper[h][k] > 0) continue; else { flg = false; break; } } if (flg) height++; else break; } flg = true; for (int h = i+1; h <= 100; ++h) { for (int k = j - paper[i][j] + 1; k <= j; ++k) { if (H[k] > 0 && paper[h][k] > 0) continue; else { flg = false; break; } } if (flg) height++; else break; } if (max < height * width) max = height * width; } } } printf("%d\n", max); return 0; } | cs |
실력키우기 남은 두 문제 중 한개... 이제 하나만 더 풀면 실력키우기를 다 푼게 된다. 드디어 ㅠㅠ
이 문제는 사실 이렇게 막 풀면 풀 수도 있긴 한데 더 짧게 뭔가 더 생각을 하면 더 효율적으로 풀 수 있을 것 같다.
일단 이 문제를 푼 방법은
1. 각 점에 대하여 x축으로 0부터 현재 위치까지 가장 큰 가로 길이를 구한다.
2. 각 점마다 y축으로 위 아래 둘다 동일하게 가로를 가졌는지 확인하며 높이를 구한다.
모든 점에 대하여 이런 과정을 거치면 각 점에 대한 결과가 나오게 된다.
예제 입력을 그림으로 나타내 보면(100 x 100으로 나타내면 너무 크기 때문에 30 x 30정도로 나타내면)
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
사실 배열로 하면 위의 코드에서 paper[x][y]이기 때문에 그림과 x축은 동일하나 y축은 반대가 된다...
때문에 위와 같은 모양이 된다.
이때 각 점(색종이가 있는 점 - 1)에 대하여 x축으로 얼마나 긴지 확인하는 로직이 36라인과 같다.
이렇게 모든 점에 대해 좌측으로부터 자신까지의 가장 긴 x길이를 구하고 나면
각 점에 대해 위쪽, 아래쪽으로 각각 검색해보며 이 길이를 만족하는지 확인하는 로직이 각각 58, 76의 for loop이다.
이렇게 구한 width, height를 곱하면 각 점에서의 최대 직사각형 넓이가 된다.
내가 봐도 코드가 너무 실수할 구석이 많다... 뭔가 더 쉬운 방법이 있을 것 같다.
'PARK > ALGORITHM' 카테고리의 다른 글
알고리즘 & BOJ 2616 소형기관차(C++) (2) | 2016.10.21 |
---|---|
BOJ 9251 LCS(C++) (1) | 2016.10.11 |
실력키우기 연속부분최대곱(C++) (1) | 2016.09.28 |
koitp 세금(TAX)(C++) (0) | 2016.09.27 |
실력키우기 하노이의 탑(C++) (0) | 2016.09.27 |