Study/Coding Test
[백준] 마법사 상어와 파이어볼
_gayeon
2021. 10. 17. 01:01
https://www.acmicpc.net/problem/20056
20056번: 마법사 상어와 파이어볼
첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다. 서로 다른 두 파이어볼의 위치
www.acmicpc.net
너무 고생했던 문제.....
고생 포인트
1. memset을 이용해 vector를 복사하려 했던 것.....
+ arr[i][j] vector를 resize 시킨 후 copy해야한다.
vector<vector<int>> arr[51][51];
void copy_vec(vector< vector<int> > temp[][51]) {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
arr[i][j].resize(temp[i][j].size());
copy(temp[i][j].begin(), temp[i][j].end(), arr[i][j].begin());
}
}
}
2. 런타임에러 발생...
s가 너무 큰경우를 고려하지 않음. -> s % N으로 처리
3. 시간 초과 발생
-> vector<int> fireball를 생성하여 따로 정보 저장.
4. 질량이 0인 파이어볼은 소멸된다 조건 누락...
9시 20분에 시작해 12시 50분에 끝나버림....
#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
int N, M, K;
vector<vector<int>> arr[51][51];
vector<vector<int>> fireball;
int answer;
int dr[8] = { -1,-1,0,1,1,1,0,-1 };
int dc[8] = { 0,1,1,1,0,-1,-1,-1 };
void init() {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
arr[i][j] = {};
}
}
}
void input() {
cin >> N >> M >> K;
int r, c, m, s, d;
for (int i = 0; i < M; i++) {
cin >> r >> c >> m >> s >> d;
arr[r][c].push_back({ r,c,m,s,d });
fireball.push_back({ r,c,m,s,d });
}
}
void print() {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
for (int k = 0; k < arr[i][j].size(); k++) {
cout << i << " " << j << " " << arr[i][j][k][2] << " " << arr[i][j][k][3] << " "<< arr[i][j][k][4] << endl;
}
}
}
cout << "--------------" << endl;
}
void copy_vec(vector< vector<int> > temp[][51]) {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
arr[i][j].resize(temp[i][j].size());
copy(temp[i][j].begin(), temp[i][j].end(), arr[i][j].begin());
}
}
}
void solve() {
//1. 모든 파이어볼 이동.
init();
for (int i = 0; i < fireball.size(); i++) {
int r = fireball[i][0];
int c = fireball[i][1];
int m = fireball[i][2]; //질량
int s = fireball[i][3]; //속력
int d = fireball[i][4]; //방향
int nr = r + dr[d] * (s % N);
if (nr > N) {
nr -= N;
}
else if (nr <= 0) {
nr += N;
}
int nc = c + dc[d] * (s % N);
if (nc > N) {
nc -= N;
}
else if (nc <= 0) {
nc += N;
}
fireball[i][0] = nr;
fireball[i][1] = nc;
arr[nr][nc].push_back({ nr,nc,m,s,d });
}
//2.
vector<vector<int>> temp; //나누어진 4개의 파이어볼
for (int r = 1; r <= N; r++) {
for (int c = 1; c <= N; c++) {
vector<vector<int>> fireballs = arr[r][c];
if (fireballs.size() == 0) {
continue;
}
else if (fireballs.size() == 1) {
temp.push_back(fireballs[0]);
}
else { //2개 이상의 파이어볼인 경우
int m_sum = 0;
int s_sum = 0;
vector<int> dir_sum;
int total = fireballs.size(); //파이어볼의 개수
for (int f = 0; f < total; f++) {
m_sum += fireballs[f][2]; //질량의 합
s_sum += fireballs[f][3]; //속력의 합
dir_sum.push_back(fireballs[f][4]);
}
//방향 홀짝 확인
int dir = dir_sum[0]%2;
int new_dir = 0; //true면 방향이 모두 홀수이거나 모두 짝수
for (int i = 1; i < total; i++) {
if (dir != dir_sum[i] % 2) {
new_dir = 1;
break;
}
}
//4개의 파이어볼로 나누어진다.
int new_m = m_sum / 5;
if (new_m > 0) {
for (int i = 0, d = 0 + new_dir; i < 4; i++, d += 2) {
temp.push_back({ r, c, new_m, s_sum / total, d });
}
}
}
}
}
init();
fireball = {};
for (int i = 0; i < temp.size(); i++) {
arr[temp[i][0]][temp[i][1]].push_back(temp[i]);
fireball.push_back(temp[i]);
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
//freopen("input.txt", "r", stdin);
init();
input();
for (int i = 0; i < K; i++) {
solve();
}
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (arr[i][j].size() > 0) {
for (int k = 0; k < arr[i][j].size(); k++) {
answer += arr[i][j][k][2];
}
}
}
}
cout << answer << endl;
return 0;
}