-
JUNGOL...136일지 2021. 9. 13. 01:44
Intermediate_Coder/자료구조/색종이(고)
문제
가로, 세로의 크기가 각각 100인 정사각형 모양의 흰색 도화지가 있다.
이 도화지 위에 가로, 세로의 크기가 각각 10인 정사각형 모양의 검은색 색종이를 색종이의 변과 도화지의 변이 평행하도록 붙인다.
이러한 방식으로 색종이를 한 장 또는 여러 장 붙인 후 도화지에서 검은색 직사각형을 잘라내려고 한다.
직사각형 또한 그 변이 도화지의 변과 평행하도록 잘라내어야 한다.
예를 들어 흰색 도화지 위에 세 장의 검은색 색종이를 <그림 1>과 같은 모양으로 붙였다.
<그림 1>에 표시된 대로 검은색 직사각형을 잘라내면 그 넓이는 22×5=110이 된다.
반면 <그림 2>에 표시된 대로 검은색 직사각형을 잘라내면 그 넓이는 8×15=120이 된다.
검은색 색종이의 수와 각 색종이를 붙인 위치가 주어질 때 잘라낼 수 있는 검은색 직사각형의 최대 넓이를 구하는 프로그램을 작성하시오.
*주의. 직사각형은 정사각형을 포함한다.
입력 형식
첫째 줄에 색종이의 수가 주어진다. 이어 둘째 줄부터 한 줄에 하나씩 색종이를 붙인 위치가 주어진다.
색종이를 붙인 위치는 두 개의 자연수로 주어지는데 첫 번째 자연수는 색종이의 왼쪽 변과 도화지의 왼쪽 변 사이의 거리이고, 두 번째 자연수는 색종이의 아래쪽 변과 도화지의 아래쪽 변 사이의 거리이다.
색종이의 수는 100 이하이며, 색종이가 도화지 밖으로 나가는 경우는 없다.
출력 형식
첫째 줄에 잘라낼 수 있는 검은색 직사각형의 최대 넓이를 출력한다.
입력 예
3
3 7
15 7
5 2출력 예
120
ColoredPaper3.h
#include <iostream> #include <stack> using std::stack; class ColoredPaper3 : public Base { private: struct Point { Point(int x, int y, int width) : x(x), y(y), width(width), isBasePoint(false) {} Point() : x(0), y(0), width(0), isBasePoint(false) {} int x; int y; int width; bool isBasePoint; }; void FillArr(bool** arr, Point p); int CheckArea(bool** arr, stack<Point>& pointStack); int GetCurLineWidth(bool** arr, int x, int y); };
ColoredPaper3.cpp
void ColoredPaper3::Code() { bool** arr = new bool*[100]; for (int i = 0; i < 100; i++) { arr[i] = new bool[100]; std::fill_n(arr[i], 100, false); } int n; std::cin >> n; stack<Point> pointStack; for (int i = 0; i < n; i++) { Point p; std::cin >> p.x >> p.y; p.isBasePoint = true; pointStack.push(p); FillArr(arr, p); } int maxArea{ 100 }; while(!pointStack.empty()) { int area{ CheckArea(arr, pointStack) }; if (area > maxArea) { maxArea = area; } } std::cout << maxArea; for (int i = 0; i < 100; i++) { delete[] arr[i]; } delete[] arr; } /// <summary> /// 입력된 위치에 색종이를 채워준다. /// </summary> /// <param name="arr">배열</param> /// <param name="x">x 시작 인덱스</param> /// <param name="y">y 시작 인덱스</param> void ColoredPaper3::FillArr(bool** arr, Point p) { for (int i = p.y; i < p.y + 10; i++) { for (int j = p.x; j < p.x + 10; j++) { arr[i][j] = true; } } } /// <summary> /// 주어진 좌표에서 시작하는 최대 넓이를 확인하여 반환한다. /// </summary> /// <param name="arr">배열</param> /// <param name="x">x 시작 인덱스</param> /// <param name="y">y 시작 인덱스</param> /// <returns>넓이</returns> int ColoredPaper3::CheckArea(bool** arr, stack<Point>& pointStack) { Point p{ pointStack.top() }; pointStack.pop(); int x{ p.x }, y{ p.y }; int width{ p.width > 0 ? p.width : GetCurLineWidth(arr, x, y) }; int count{ 0 }; int lastAddedWidth{ 0 }; int area{ 0 }; for (int i = y; i < 100; i++) { int curWidth{ GetCurLineWidth(arr, x, i) }; if (curWidth >= width) { count++; area = width * count; if (p.isBasePoint && lastAddedWidth != curWidth) { pointStack.push(Point(x, i, curWidth)); lastAddedWidth = curWidth; } } else { if (p.isBasePoint && curWidth > 0) { pointStack.push(Point(x, y, curWidth)); } break; } } return area; } /// <summary> /// 주어진 좌표의 너비를 반환한다. /// </summary> /// <param name="arr">배열</param> /// <param name="x">x 시작 인덱스</param> /// <param name="y">y 시작 인덱스</param> /// <returns>해당 라인의 넓이</returns> int ColoredPaper3::GetCurLineWidth(bool** arr, int x, int y) { int width{ 0 }; for (int i = x; i < 100; i++) { if (!arr[y][i]) { break; } width++; } return width; }
실행 결과 Accepted(60)
원인 기본으로 주어진 포인트에서 발견된 넓어지는 부분은 새로운 포인트로 추가하여 계산했으나 여전히 놓치는 부분이 있는 것 같다.
처리 방법 무한루프에 빠지지 않으면서 모든 시작 지점을 찾는 방법을 고민해 봐야겠다.
NadanKim/CodingTest_JUNGOL: JUNGOL 코딩 테스트를 위한 저장소 (github.com)