소용돌이 예쁘게 출력하기
1.설계(20)
-
문제 해석
- 중심좌표(0,0)를 기준으로 반시계방향으로 돌면서 숫자를 채운 후, (r1,c1) ~ (r2,c2) 좌표의 숫자들을 출력하는 문제입니다.
- 숫자들을 출력할 때, 각 끝자리 수가 알맞게 정렬되도록 출력해야 합니다.
- -5000 <= r1,c1,r2,c2 <= 5000, 0 <= r2-r1 <= 49, 0 <= c2 - c1 <= 4
-
설계
- 첫번째로 그리는 방법을 생각해야 합니다. dir배열을 주어 (오른쪽,위), (왼쪽,아래) 방향일때, 해당 방향으로 len길이만큼 숫자를 채워나갑니다. 방향이 두번 변화할 때마다 len을 늘려주면 됩니다.
- 처음에는 10000^2 공간배열을 만들어 숫자를 채우려고 하였으나, 메모리 제한이 걸려서 원하는 숫자범위만 저장하도록 하였습니다.
- 두번째로 출력을 할 때, 출력범위에서 가장 큰 숫자를 찾아야 합니다. 그리기를 할 때, 만약 숫자범위에 들어가면 최대 숫자 길이를 갱신 하도록 하였습니다.
- 각 숫자에 대해서 (최대 숫자 길이-숫자 길이)만큼 공간을 더 주고 출력하면 됩니다.
2.구현(40)
- 코드
#include <iostream>
#include <vector>
#include <string>
using namespace std;
#define OFFSET 5000
vector<string> map;
int len = 1;
int cnt = 0;
int r1, c1, r2, c2;
int dx[] = { 0,-1,0,1 };
int dy[] = { 1,0,-1,0 };
int max_num = 0;
bool is_range1(int x, int y) {
if (x < r1 || y < c1 || x > r2 || y > c2) return false;
return true;
}
void make(vector<vector<string> > & map) {
int x = OFFSET;
int y = OFFSET;
int nx = x;
int ny = y;
int dir = 0;
int dir_cnt = 0;
int num = 2;
int total_cnt = (r2 - r1 + 1) * (c2 - c1 + 1);
while (cnt < total_cnt) {
for (int i = 0; i < len; i++) {
nx += dx[dir];
ny += dy[dir];
if (is_range1(nx, ny)) {
map[nx - r1][ny - c1] = to_string(num);
cnt++;
int tmp_len = map[nx-r1][ny - c1].length();
if (max_num < tmp_len) max_num = tmp_len;
}
num++;
}
dir = (dir + 1) % 4;
dir_cnt++;
if (dir_cnt == 2) {
dir_cnt = 0;
len++;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> r1 >> c1 >> r2 >> c2;
r1 += OFFSET;
c1 += OFFSET;
r2 += OFFSET;
c2 += OFFSET;
vector<vector<string> > map(r2 - r1 + 1, vector<string>(c2 - c1 + 1));
if (is_range1(OFFSET, OFFSET)) {
map[OFFSET - r1][OFFSET - c1] = to_string(1);
cnt++;
int tmp_len = map[OFFSET - r1][OFFSET - c1].length();
if (max_num < tmp_len) max_num = tmp_len;
}
make(map);
for (int i = 0; i < r2 - r1 + 1; i++) {
for (int j = 0; j < c2 - c1 + 1; j++) {
int num = max_num - map[i][j].length();
while (num > 0) {
cout << " ";
num--;
}
cout << map[i][j] <<" ";
}
cout << "\n";
}
return 0;
}
-
디버깅
- 숫자 길이를 찾기 쉽도록 string형 vector를 이용하였습니다.
-
제출결과
136ms
3.마무리
- 제가 구현한 방법은 최악의 경우에 시간복잡도가 O(1억)이므로 실행시간이 그리 빠르지 않았습니다.
다른 분들의 코드를 참조해보니 해당 숫자를 바로 찾을 수 있는 수식으로 계산하여 순차적으로 그리지 않아도 되었습니다.
그러나, 이 방법을 이용하면 문제의 목적인 구현을 연습할 수 없습니다.
최적화도 좋지만 주먹구구식이긴 하여도 구현을 해보는 것도 나쁘지 않다고 생각합니다.