혜윤이는 최근에 다양한 대회를 참여하면서 노트북에 붙일 수 있는 스티커들을 많이 받았다. 스티커는 아래와 같이 사각 모눈종이 위에 인쇄되어 있으며, 스티커의 각 칸은 상하좌우로 모두 연결되어 있다. 또한 모눈종이의 크기는 스티커의 크기에 꼭 맞아서, 상하좌우에 스티커가 포함되지 않는 불필요한 행이나 열이 존재하지 않는다.
아래는 올바른 모눈종이의 예시이다. 주황색 칸은 스티커가 붙은 칸을, 하얀색 칸은 스티커가 붙지 않은 칸을 나타낸다.
반면 아래는 올바르지 않은 모눈종이의 예시이다. 첫 번째는 윗쪽에 불필요한 행이 있고, 두 번째는 왼쪽에 불필요한 열이 있다. 그리고 세 번째는 스티커의 각 칸이 상하좌우로 모두 연결되어 있지 않다.
혜윤이는 자신의 노트북에 이 스티커들을 붙이기로 했다. 혜윤이의 노트북은 마침 직사각형 모양이고, 스티커가 인쇄된 모눈종이와 같은 간격으로 격자가 그려져 있다. 혜윤이는 스티커들을 먼저 받았던 것부터 차례대로 격자에 맞춰서 붙이려고 한다.
혜윤이가 스티커를 붙이는 방법은 다음과 같다.
아래의 예시를 통해 스티커를 붙이는 과정을 이해해보자. 노트북은 세로 5칸, 가로 4칸 크기이고, 혜윤이가 가지고 있는 스티커들은 아래와 같다. 왼쪽에서 오른쪽 순으로 스티커를 붙일 것이다.
첫 번째 스티커는 회전 없이 온전히 붙일 수 있는 공간이 아래와 같이 6곳이 있다.
이 중에서 가장 위쪽의 위치, 가능한 가장 위쪽의 위치가 여러 개이면 그 중에서 가장 왼쪽의 위치는 첫 번째이다. 스티커를 붙인 후 노트북의 모양은 아래와 같다.
두 번째 스티커는 회전 없이 온전히 붙일 수 있는 공간이 없다. 그러나 시계 방향으로 90도 회전한 후에는 붙일 수 있는 공간이 1개 생긴다. 해당 공간에 스티커를 붙인 후 노트북의 모양은 아래와 같다.
세 번째 스티커는 스티커를 시계방향으로 0, 90, 180, 270도 회전시킨 모양에 대해 전부 확인을 해도 스티커를 붙일 수 있는 공간이 없다. 그러므로 해당 스티커를 붙이지 않고 버린다.
네 번째 스티커는 스티커를 시계방향으로 0, 90, 180도 회전 시킨 모양에 대해 온전히 붙일 수 있는 공간이 없다. 그러나 시계 방향으로 270도 회전한 후에는 공간이 1개 생긴다. 스티커를 붙인 후 노트북의 모양은 아래와 같다. 최종적으로 노트북의 18칸이 스티커로 채워졌다.
혜윤이는 스티커를 다 붙인 후의 노트북의 모습이 궁금해졌다. 노트북의 크기와 스티커들이 주어졌을 때 스티커들을 차례대로 붙이고 난 후 노트북에서 몇 개의 칸이 채워졌는지 구해보자.
첫째 줄에 노트북의 세로와 가로 길이를 나타내는 N(1 ≤ N ≤ 40)과 M(1 ≤ M ≤ 40), 그리고 스티커의 개수 K(1 ≤ K ≤ 100)이 한 칸의 빈칸을 사이에 두고 주어진다.
그 다음 줄부터는 K개의 스티커들에 대한 정보가 주어진다. 각 스티커는 아래와 같은 형식으로 주어진다.
먼저 i번째 스티커가 인쇄된 모눈종이의 행의 개수와 열의 개수를 나타내는 Ri(1 ≤ Ri ≤ 10)와 Ci(1 ≤ Ci ≤ 10)가 한 칸의 빈칸을 사이에 두고 주어진다.
다음 Ri개의 줄에는 각 줄마다 모눈종이의 각 행을 나타내는 Ci개의 정수가 한 개의 빈칸을 사이에 두고 주어진다. 각 칸에 들어가는 값은 0, 1이다. 0은 스티커가 붙지 않은 칸을, 1은 스티커가 붙은 칸을 의미한다.
문제에서 설명한 것과 같이 스티커는 모두 올바른 모눈종이에 인쇄되어 있다. 구체적으로 스티커의 각 칸은 상하좌우로 모두 연결되어 있고, 모눈종이의 크기는 스티커의 크기에 꼭 맞아서 상하좌우에 스티커에 전혀 포함되지 않는 불필요한 행이나 열이 존재하지 않는다.
첫째 줄에 주어진 스티커들을 차례대로 붙였을 때 노트북에서 스티커가 붙은 칸의 수를 출력한다.
정처기 밀렸다.... 공기업, 사기업 같이 준비하려하니 요즘 진짜 멘탈 잡기 힘들다. 분노의 알고리즘 풀이 ㅋㅋ;;
친구가 삼성 기출이랑 가장 비슷한 문제라고 말해줘서 풀었던 문제다. 3시간 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
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
120
121
|
#include <iostream>
using namespace std;
int n,m,k,ans;
int r[100], c[100];
bool sticker[4][100][10][10]; //0
bool MAP[40][40];
bool can(int x, int y, int a, int angle)
{
switch(angle)
{
case 0:case 2:
for(int i=0;i<r[a];i++)
for(int j=0;j<c[a];j++)
{
if(x+i>=n||y+j>=m) return false;
if(MAP[x+i][y+j]&&sticker[angle][a][i][j])
return false;
}
break;
case 1:case 3:
for(int i=0;i<c[a];i++)
for(int j=0;j<r[a];j++)
{
if(x+i>=n||y+j>=m) return false;
if(MAP[x+i][y+j]&&sticker[angle][a][i][j])
return false;
}
break;
}
return true;
}
void marking(int x, int y, int a, int angle)
{
switch(angle)
{
case 0:case 2:
for(int i=0;i<r[a];i++)
for(int j=0;j<c[a];j++)
{
bool temp = (MAP[x+i][y+j] || sticker[angle][a][i][j]);
MAP[x+i][y+j] = temp;
}
return;
case 1:case 3:
for(int i=0;i<c[a];i++)
for(int j=0;j<r[a];j++)
{
bool temp = (MAP[x+i][y+j] || sticker[angle][a][i][j]);
MAP[x+i][y+j] = temp;
}
return;
}
}
void attach(int a)
{
for(int angle = 0;angle<4;angle++)
{
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(can(i,j,a,angle))
{
marking(i,j,a,angle);
// cout<<"Sticker : "<<a<<'\n';
// cout<<"Angle : "<<angle<<'\n';
// cout<<"At : "<<i<<' '<<j<<'\n';
// for(int aa = 0;aa<n;aa++)
// {
// for(int bb = 0 ;bb<m;bb++)
// {
// cout<<MAP[aa][bb]<<' ';
// }
// cout<<'\n'; //현재 스티커 붙은 모습 확인
// }
return;
}
}
}
void solve()
{
for(int a = 0;a<k;a++)
attach(a);
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int temp;
cin>>n>>m>>k;
for(int a = 0;a<k;a++)
{
cin>>r[a]>>c[a];
for(int i=0;i<r[a];i++)
for(int j=0;j<c[a];j++)
{
cin>>temp;
sticker[0][a][i][j] = temp;
sticker[1][a][j][r[a]-1-i] = temp;
sticker[2][a][r[a]-1-i][c[a]-1-j] = temp;
sticker[3][a][c[a]-1-j][i] = temp;
}
}
solve();
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(MAP[i][j]) ans++;
cout<<ans<<'\n';
return 0;
}
|
cs |
코드가 좀 길다.
입력부터 설명하겠다.
1. 스티커를 입력 받는데 4방향 행렬을 모두 준비한다.
2. k개의 스티커를 4방향으로 돌려서 입력을 받아 집어 넣는다. rotate 함수 구현하는게 더 번거로울 것 같아서 이렇게 했다.
3. 각 스티커의 row와 column 크기도 기억해야 하므로 따로 행렬로 저장한다.
알고리즘
1. 입력 받은 순서대로 스티커를 붙인다고 하였으므로 행렬에 저장되어 있는 첫 번째 스티커 부터 시작한다.
2. 정방향 스티커 부터 시작해서 붙일 수 있는지 체크한다. 맨 왼쪽 위부터 붙인다고 하였으니까 자연스레 0,0부터 보면 된다.
3.체크하는 함수는 범위를 벗어나거나 MAP과 스티커 둘 다 1일 경우에 false를 리턴하고 모든 check를 통과하면 true를 리턴한다.
4. 체크 했으면 붙인다. 이 때, 중요한건 or연산으로 붙여야 한다. 붙였으면 return하고 다음 스티커 진행한다.
2~4를 모든 스티커에 대해서 시행한 후 MAP행렬의 true개수를 출력한다.
참고
switch문의 0, 2와 1,3은 각각 row와 column의 크기가 같다.
14502. 연구소 GOLD V(C++) (0) | 2020.04.23 |
---|---|
17144. 미세먼지 안녕! GOLD V (C++) (0) | 2020.04.21 |
2696. 중앙값 구하기 (1) | 2020.03.12 |
1927. 최소 힙 (0) | 2020.03.05 |
11286. 절댓값 힙 (0) | 2020.03.05 |
댓글 영역