ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 - 20056 [C++]
    문제 풀이/백준 2023. 7. 18. 23:26
    반응형

     이 문제는 시뮬레이션 문제이다. 시뮬레이션 문제 특성상 구현이 매우 복잡하지만 일단 구현하면 문제는 풀린다. 문제를 제대로 읽지 않아서 이동 시 범위를 넘어갔을 때 다시 순환형으로 돌아온다는 사실을 모르고 구현했다가 다시 풀었다. 모듈러 연산을 활용하여 연산 횟수를 줄이기 위해서는 인덱스가 1로 시작하면 매우 복잡하다. 따라서 입력을 받을 때 r과 c를 1씩 빼서 0부터 시작하도록 수정하였고, matrix의 한 요소를 벡터로 하여 항상 push 할 수 있도록 하여 구현을 그나마 간단하게 하였다. 

     어려운 구현 문제는 꼭 함수를 분리하여 추상화를 먼저 하고 순서를 짜놓은 뒤 세부 구현을 하는게 훨씬 간편하다.

     

     

     

    #include <iostream>
    #include <vector>
    #include <queue>
    
    using namespace std;
    
    #define UP		0
    #define UPRIGHT		1
    #define RIGHT		2
    #define DOWNRIGHT	3
    #define DOWN		4
    #define DOWNLEFT	5
    #define LEFT		6
    #define UPLEFT		7
    
    typedef struct _fireball
    {
    	int r;
    	int c;
    	int m;
    	int s;
    	int d;
    } fireball;
    
    vector<vector<vector<fireball>>> matrix;	// 격자
    int n;	// 격자 크기
    int f;	// fireball count
    int k;	// command count
    
    bool moveFunc(fireball& present)
    {
    	int direction = present.d;
    	int startR = present.r;
    	int startC = present.c;
    	int speed = present.s;
    	int endR = startR;
    	int endC = startC;
    
    	switch (direction)
    	{
    	case UP:
    		endR = (startR - speed) % n;
    		if (endR < 0)
    		{
    			endR += n;
    		}
    		break;
    
    	case UPRIGHT:
    		endR = (startR - speed) % n;
    		if (endR < 0)
    		{
    			endR += n;
    		}
    		endC = (startC + speed) % n;
    		break;
    
    	case RIGHT:
    		endC = (startC + speed) % n;
    		break;
    	
    	case DOWNRIGHT:
    		endR = (startR + speed) % n;
    		endC = (startC + speed) % n;
    		break;
    	
    	case DOWN:
    		endR = (startR + speed) % n;
    		break;
    	
    	case DOWNLEFT:
    		endR = (startR + speed) % n;
    		endC = (startC - speed) % n;
    		if (endC < 0)
    		{
    			endC += n;
    		}
    		break;
    	
    	case LEFT:
    		endC = (startC - speed) % n;
    		if (endC < 0)
    		{
    			endC += n;
    		}
    		break;
    	
    	case UPLEFT:
    		endR = (startR - speed) % n;
    		if (endR < 0)
    		{
    			endR += n;
    		}
    		endC = (startC - speed) % n;
    		if (endC < 0)
    		{
    			endC += n;
    		}
    		break;
    	}
    	
    	present.r = endR;
    	present.c = endC;
    
    	return true;
    }
    
    void move()
    {
    	vector<vector<vector<fireball>>> tempMatrix(51, vector<vector<fireball>>(51, vector<fireball>()));
    
    	for (int y = 0; y < n; y++)
    	{
    		for (int x = 0; x < n; x++)
    		{
    			if (matrix[y][x].empty())
    			{
    				continue;
    			}
    
    			for (fireball temp : matrix[y][x])
    			{
    				bool result;
    
    				result = moveFunc(temp);
    
    				if (result)
    				{
    					tempMatrix[temp.r][temp.c].push_back(temp);
    				}
    			}
    		}
    	}
    
    	matrix = tempMatrix;
    }
    
    void sumAndDivide()
    {
    	vector<vector<vector<fireball>>> tempMatrix(51, vector<vector<fireball>>(51, vector<fireball>()));
    
    	for (int y = 0; y < n; y++)
    	{
    		for (int x = 0; x < n; x++)
    		{
    			if (matrix[y][x].size() == 1)
    			{
    				tempMatrix[y][x].push_back(matrix[y][x].front());
    			}
    
    			if (matrix[y][x].size() >= 2)
    			{
    				fireball result;
    				int size = matrix[y][x].size();
    				int mSum = 0;
    				int sSum = 0;
    				int direction = matrix[y][x].front().d;
    				bool correct = true;
    				int oddOrEven = -1;
    
    				if (direction % 2 == 0)
    				{
    					oddOrEven = 0;
    				}
    				else
    				{
    					oddOrEven = 1;
    				}
    
    				for (auto& temp : matrix[y][x])
    				{
    					mSum += temp.m;
    					sSum += temp.s;
    
    					if (oddOrEven == 0)	// even
    					{
    						if (temp.d % 2 == 1)
    						{
    							correct = false;
    						}
    					}
    					else			// odd
    					{
    						if (temp.d % 2 == 0)
    						{
    							correct = false;
    						}
    					}
    				}
    
    				matrix[y][x].clear();
    
    				if (mSum / 5 != 0)
    				{
    					if (correct)
    					{
    						int ds[] = { 0, 2, 4, 6 };
    
    						for (int i = 0; i < 4; i++)
    						{
    							tempMatrix[y][x].push_back({ y, x, mSum / 5, sSum / size, ds[i] });
    						}
    					}
    					else
    					{
    						int ds[] = { 1,3,5,7 };
    
    						for (int i = 0; i < 4; i++)
    						{
    							tempMatrix[y][x].push_back({ y, x, mSum / 5, sSum / size, ds[i] });
    						}
    					}
    				}
    			}
    		}
    	}
    
    	matrix = tempMatrix;
    }
    
    int main()
    {
    	ios_base::sync_with_stdio(0);
    	cin.tie(0);
    
    	int answer = 0;
    
    	cin >> n >> f >> k;
    
    	matrix = vector<vector<vector<fireball>>>(51, vector<vector<fireball>>(51, vector<fireball>()));
    
    	for (int i = 0; i < f; i++)
    	{
    		int r, c, m, d, s;	// 행, 열, 질량, 방향, 속력
    
    		cin >> r >> c >> m >> s >> d;
    
    		matrix[r - 1][c - 1].push_back({ r - 1, c - 1, m, s, d });
    	}
    
    	for (int i = 0; i < k; i++)
    	{
    		move();
    
    		sumAndDivide();
    	}
    
    	for (int y = 0; y < n; y++)
    	{
    		for (int x = 0; x < n; x++)
    		{
    			for (fireball& temp : matrix[y][x])
    			{
    				answer += temp.m;
    			}
    		}
    	}
    
    	cout << answer << '\n';
    
    	return 0;
    }
    반응형

    '문제 풀이 > 백준' 카테고리의 다른 글

    백준 - 15591 [C++]  (0) 2023.07.29
    백준 - 17837 [C++]  (0) 2023.07.20
    백준 - 12851 [C++]  (0) 2023.07.18
    백준 - 9466 [C++]  (2) 2023.07.18
    백준 - 2146 [C++]  (0) 2023.07.18
Designed by Tistory.