5648. 원자 소멸 시뮬레이션
최악의 경우를 떠올려봐도...시간통과될 것 같은데 왜 안되는것인지 모르겠다...ㅠㅠ
SW EXPERT 에 질문을 올렸더니, 한분께서 STL QUEUE 가 속도가 느린것 같다고, 배열로 만들어서 해보면 통과라고 했는데 정말 됐다.
어떠한 이유인지 정확히 모르겠으나, STL 의 QUEUE가 삽입,삭제 연산이나 이런부분에서 속도가 좀 저하되는 것 같다.
이 문제는 푸는 과정에서 시간초과가 정말 많이 났다.
맨 처음에는 생각했던 방식은
1. 모든 점들을 이동 → 2. 겹쳐지는 점들을 다시 탐색 → 3. 겹친점들 제거 → 4. 맵 초기화 방식 으로 순서적으로 진행하였다.
하지만 시간초과 해결을 못해서 이리저리 낑낑대고 인터넷으로 다른 분들 보면서 최적의 정답 코드로 수정했다.
그러나 처음 정답 코드도 큐를 배열로 짰더니 통과하였다.
최종 정답 코드 에서는 맨 처음에 했던 방식의 점들을 이동하고 겹쳐지는 점들을 탐색하고 제거하는 과정을 하나로 만들어냈다.
원자들의 값을 하나의 셀에 축적시키고 나중에 돌아왔을 때 해결하는 방식이었다. 이때 아이디어는 축적된 에너지 값이, 내가 가지고 있는 에
너지값보다 크면 셀이 축적되었다 라는 아이디어였다. 그 아이디어를 통해서 위의 과정을 통합하면서 코드가 좀 통합된 느낌...?
<최종 정답 코드>
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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | #include<iostream> #define MAXSIZE 1000 #define ADD 1000 #define MAX 4001 using namespace std; typedef struct atom { int x; int y; int dir; int energy; }atom; int dx[] = { 1,-1,0,0 }; int dy[] = { 0,0,-1,1 }; int map[MAX][MAX]; atom q[MAXSIZE]; int front; int rear; int qsize; bool empty() { if (front==rear) return true; else return false; } bool full() { if ((rear+1)%MAXSIZE == front) return true; else return false; } void push(atom tmp) { if (full()) return; qsize++; q[rear] = tmp; rear = (rear + 1) % MAXSIZE; } atom pop() { atom ret = { 0,0,0,0 }; if (empty()) return ret; qsize--; ret = q[front]; front = (front + 1) % MAXSIZE; return ret; } int main() { ios::sync_with_stdio(false); cin.tie(NULL); //freopen("input.txt", "r", stdin); int tc; cin >> tc; for (int t = 1; t <= tc; t++) { int N, ans = 0; cin >> N; for (int i = 0; i < N; i++) { int x, y, d, e; cin >> y >> x >> d >> e; x += ADD; y += ADD; x *= 2; y *= 2; map[x][y] = e; atom tmp = { x,y,d,e }; push(tmp); } while (!empty()) { // 원자 이동하기 int size = qsize; for (int i = 0; i < size; i++) { atom now = pop(); int x = now.x; int y = now.y; int d = now.dir; int e = now.energy; int nx = x + dx[d]; int ny = y + dy[d]; atom moved = { nx,ny,d,e }; // 현재 지점이 원자가 충돌된 지점일 때 if (now.energy < map[x][y]) { ans += map[x][y]; map[x][y] = 0; continue; } // 이동할 곳의 범위 체크 if (nx >= 0 && ny >= 0 && nx < MAX && ny < MAX) { // 이동할 곳에 원자가 있을 때 if (map[nx][ny] != 0) map[nx][ny] += e; // 이동할 곳에 원자가 없을 때 else { map[nx][ny] = e; push(moved); } } // 원자 삭제 map[x][y] = 0; } } cout << "#" << t << " " << ans << endl; } return 0; } | cs |
<정답 코드 - 맨 처음에 풀었던 방법 >
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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | #include<iostream> #include<vector> #define MAXSIZE 1000 #define ADD 1000 #define MAX 4001 using namespace std; typedef struct atom { int x; int y; int dir; int energy; }atom; int dx[] = { 1,-1,0,0 }; int dy[] = { 0,0,-1,1 }; int map[MAX][MAX]; atom q[MAXSIZE]; int front; int rear; int qsize; bool empty() { if (front==rear) return true; else return false; } bool full() { if ((rear+1)%MAXSIZE == front) return true; else return false; } void push(atom tmp) { if (full()) return; qsize++; q[rear] = tmp; rear = (rear + 1) % MAXSIZE; } atom pop() { atom ret = { 0,0,0,0 }; if (empty()) return ret; qsize--; ret = q[front]; front = (front + 1) % MAXSIZE; return ret; } int main() { ios::sync_with_stdio(false); cin.tie(NULL); //freopen("input.txt", "r", stdin); int tc; cin >> tc; for (int t = 1; t <= tc; t++) { int N, ans = 0; cin >> N; for (int i = 0; i < N; i++) { int x, y; atom tmp; cin >> y >> x >> tmp.dir >> tmp.energy; tmp.x = x + ADD; tmp.x *= 2; tmp.y = y + ADD; tmp.y *= 2; map[tmp.x][tmp.y]++; push(tmp); } while (!empty()) { // 점들 이동하기 int size = qsize; for (int i = 0; i < size; i++) { atom cur = pop(); int x =cur.x; int y = cur.y; int dir = cur.dir; int energy = cur.energy; int nx = x + dx[dir]; int ny = y + dy[dir]; atom moved = { nx,ny,dir,energy }; map[x][y]--; // 범위 벗어나면 제외 if (nx >= 0 && ny >= 0 && nx < MAX && ny < MAX) { map[nx][ny]++; push(moved); } } // 겹치는 곳들 삭제 vector<pair<int, int>> temp; size = qsize; for (int i = 0; i < size; i++) { atom cur = pop(); int x = cur.x; int y = cur.y; int dir = cur.dir; int energy = cur.energy; int nx = x + dx[dir]; int ny = y + dy[dir]; atom moved = { nx,ny,dir,energy }; if (map[x][y] > 1) { ans += energy; temp.push_back({ x,y }); } else push(cur); } // 맵 초기화 for (int i = 0; i < temp.size(); i++) { map[temp[i].first][temp[i].second] = 0; } } cout << "#" << t << " " << ans << endl; } return 0; } | cs |
<시간 초과 코드>
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 | #include<iostream> #include<queue> #define ADD 1000 #define MAX 4001 using namespace std; typedef struct atom { int x; int y; int dir; int energy; }atom; int dx[] = { 1,-1,0,0 }; int dy[] = { 0,0,-1,1 }; int map[MAX][MAX]; int main() { ios::sync_with_stdio(false); cin.tie(NULL); freopen("input.txt", "r", stdin); int tc; cin >> tc; for (int t = 1; t <= tc; t++) { int N, ans = 0; cin >> N; queue<atom> q; for (int i = 0; i < N; i++) { int x, y, d, e; cin >> y >> x >> d >> e; x += ADD; y += ADD; x *= 2; y *= 2; map[x][y] = e; atom tmp = { x,y,d,e }; q.push(tmp); } while (!q.empty()) { // 원자 이동하기 int size = q.size(); for (int i = 0; i < size; i++) { int x = q.front().x; int y = q.front().y; int d = q.front().dir; int e = q.front().energy; int nx = x + dx[d]; int ny = y + dy[d]; atom now = { x,y,d,e }; atom moved = { nx,ny,d,e }; q.pop(); // 현재 지점이 원자가 충돌된 지점일 때 if (now.energy < map[x][y]) { ans += map[x][y]; map[x][y] = 0; continue; } // 이동할 곳의 범위 체크 if (nx >= 0 && ny >= 0 && nx < MAX && ny < MAX) { // 이동할 곳에 원자가 있을 때 if (map[nx][ny] != 0) map[nx][ny] += e; // 이동할 곳에 원자가 없을 때 else { map[nx][ny] = e; q.push(moved); } } // 원자 삭제 map[x][y] = 0; } } cout << "#" << t << " " << ans << endl; } return 0; } | cs |
반응형
'알고리즘 > SW EXPERT' 카테고리의 다른 글
4583. 세븐 카드 섞기 게임 (0) | 2018.10.06 |
---|---|
5432. 쇠막대기 자르기 (0) | 2018.10.06 |
5653. 줄기세포배양 (2) | 2018.10.02 |
5658. 보물상자 비밀번호 (0) | 2018.10.02 |
5656. 벽돌깨기 (0) | 2018.10.01 |