SWExpertAcademy의 수정이의 타일 자르기(1812) 문제이다.
[ 문제풀이 ]
먼저, 주어진 TestCase를 가지고, 어떤 경우에 타일이 필요한지, 그리고 타일을 수직 - 수평 방향으로 자르게 되면 어떤 타일이 남게 되는지, 이에 따라서 정답이 어떻게 나오게 되는지부터 알아보자.
#1. 사각형 자르기
TestCase2번을 한번 확인해보자.
TestCase2번에서 수정이가 필요한 정사각형은 길이가 '4'인 2개의 정사각형이 필요하다.
그리고 가게에서는 길이가 '5'인 정사각형만 판다고 되어있다.
그럼 그림으로 한번 나타내보자.
.
위의 그림과 같이 필요한 정사각형은 한변의 길이가 4인 정사각형 2개가 필요하고, 가게에서 판매하는 정사각형은 길이가 5인 정사각형만 판매한다는 것이다.
( 지금부터는 단순하게 "길이가 x인 정사각형" 이라고 표현하겠습니다. 길이가 x인 정사각형이라는 것은, 한 변의 길이가 x인
정사각형을 의미합니다. )
먼저, 타일을 채우기 위해서 "처음에 반드시 1번은 구매" 해야 한다. 왜냐하면 처음에 기본적으로 가지고 있는 타일은 없기 때문이다. 그럼 길이가 5인 정사각형을 먼저 첫 번째 길이가 4인 정사각형을 채운다고 생각해보자.
그럼, 문제에서 제시한 대로 정사각형은 반드시 수직 - 수평의 순서대로 잘라야 하니, 길이가 5인 정사각형을 길이가 4인 정사각형에 맞게 채우기 위해서 한번 잘라보자.
먼저 수직으로 자르면 다음과 같이 잘릴 것이다.
.
위와 같이 빨강색 점선을 기준으로 자르게 될 것이고, 오른쪽 그림과 같이 2개의 사각형으로 나눠질 것이다.
하지만, 아직 길이가 4인 정사각형을 만들지는 못했으므로, 위의 사각형을 한번 더 수평으로 잘라주어야 한다.
그럼 이렇게 자를 수 있다.
.
위와 같이 한번 더 자르게 되면, 길이가 4인 정사각형을 만들수가 있게 된다.
즉, 기존에 길이가 5인 정사각형이 다음과 같이 3개의 사각형으로 나눠지게 된 것이다.
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 | #include <iostream> #include <cstring> #include <algorithm> #include <vector> #define endl "\n" #define MAX 510 using namespace std; int N, M, Answer; vector<int> Need_Tile; vector<pair<pair<int, int>, bool>> Have_Tile; void Initialize() { Answer = 0; Need_Tile.clear(); Have_Tile.clear(); } void Input() { cin >> N >> M; for (int i = 0; i < N; i++) { int a; cin >> a; int Len = 1; for (int j = 0; j < a; j++) Len <<= 1; Need_Tile.push_back(Len); } } bool Cmp(int A, int B) { return A > B ? true : false; } void Solution() { sort(Need_Tile.begin(), Need_Tile.end(), Cmp); Have_Tile.push_back(make_pair(make_pair(M, M), false)); Answer++; for (int i = 0; i < Need_Tile.size(); i++) { int Need_Len = Need_Tile[i]; bool Flag = false; for (int j = 0; j < Have_Tile.size(); j++) { if (Have_Tile[j].second == true) continue; // 이미 사용한 타일은 사용못함. int Sero = Have_Tile[j].first.first; int Garo = Have_Tile[j].first.second; if (Sero >= Need_Len && Garo >= Need_Len) { Flag = true; Have_Tile[j].second = true; if(Garo > Need_Len) Have_Tile.push_back(make_pair(make_pair(Sero, Garo - Need_Len), false)); if(Sero > Need_Len) Have_Tile.push_back(make_pair(make_pair(Sero - Need_Len, Need_Len), false)); break; } } if (Flag == false) { Answer++; if (M > Need_Len) Have_Tile.push_back(make_pair(make_pair(M, M - Need_Len), false)); if (M > Need_Len) Have_Tile.push_back(make_pair(make_pair(M - Need_Len, Need_Len), false)); } } } void Solve() { int Tc; cin >> Tc; for (int T = 1; T <= Tc; T++) { Initialize(); Input(); Solution(); cout << "#" << T << " " << Answer << endl; } } int main(void) { ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); //freopen("Input.txt", "r", stdin); Solve(); return 0; } | cs |
'[ SWEA Code ] > # SWEA - ' 카테고리의 다른 글
[ SWEA 7991 ] 줄 세우기 (C++) (0) | 2020.10.28 |
---|---|
[ SWEA 3410 ] 동서양의 경계 (C++) (0) | 2020.09.27 |
[ SWEA 5685 ] 초등학생 (C++) (0) | 2020.09.22 |
[ SWEA 7534 ] 스택 장인 (C++) (0) | 2020.09.20 |
[ SWEA 9092 ] 마라톤 (C++) (0) | 2020.09.14 |