본문 바로가기

c++/Baekjoon Online

백준 18500 : 미네랄 2 c++

https://www.acmicpc.net/problem/18500

 

18500번: 미네랄 2

창영과 상근은 한 동굴을 놓고 소유권을 주장하고 있다. 두 사람은 막대기를 서로에게 던지는 방법을 이용해 누구의 소유인지를 결정하기로 했다. 싸움은 동굴에서 벌어진다. 동굴에는 미네랄

www.acmicpc.net

 

빡구현 감 안잃기

 

포인트

1. 떨어져야할 클러스터 지정 다 한 다음에는, 최소 수직거리 구해서 통으로 내리기

 

 

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

int d_r[4] = { 1,-1,0,0 };
int d_c[4] = { 0,0,1,-1 };

int r, c;
int n;
char map[101][101];
int visited[101][101];

int gravity(int row, int col, int clu)
{
	for (int a = row + 1; a < r; a++)
	{
		if (map[a][col] == 'x')
		{
			if (visited[a][col] == clu)
				return 1000;
			else
			{
				return a - (row+1);
			}
		}
	}
	return r - (row + 1);

}


void check_map()
{
	int cnt = 1;
	memset(visited, 0, sizeof(visited));
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < c; j++)
		{
			if ((map[i][j] == 'x') && (visited[i][j] == 0))
			{
				//이게 땅까지 쭉 연결되어 있는지 확인필요
				// 어케 확인하냐, 한번이라도 바닥 즉 r에 접근했으면 true로 바꿈
				bool is_connet = false;
				vector<pair<int, int> > cluster;
				cluster.push_back(make_pair(i, j));
				visited[i][j] = cnt;
				queue<pair<int, int> > q;
				q.push(make_pair(i, j));
				while (!q.empty())
				{
					int rr = q.front().first;
					int cc = q.front().second;
					q.pop();
					for (int k = 0; k < 4; k++)
					{
						int new_r = rr + d_r[k];
						int new_c = cc + d_c[k];
						if (new_r == r)
							is_connet = true;
						if (new_r < 0 || new_c < 0 || new_r >= r || new_c >= c)
							continue;
						if (visited[new_r][new_c] != 0)
							continue;
						if (map[new_r][new_c] == '.')
							continue;
						visited[new_r][new_c] = cnt;
						cluster.push_back(make_pair(new_r, new_c));
						q.push(make_pair(new_r, new_c));
					}
				}
				// 두개의 클러스터가 동시에 떨어지는 경우는 없다!
				// 하나 뭉텅이 다 떨궜으면 return
				if (is_connet == false)
				{
					// 떨구기 시작 모양 그대로 유지하고, 지금 cnt 처리되어있는놈들을 전부 떨구기
					// 최소 수직 거리구하기
					int min_length = 1000;
					for (int k = 0; k < cluster.size(); k++)
					{
						int rrr = cluster[k].first;
						int ccc = cluster[k].second;

						min_length =  min(min_length, gravity(rrr, ccc, cnt));
					}

					//수직거리 만큼 떨구기
					for (int a = r - 1; a >= 0; a--)
					{
						for (int b = 0; b < c; b++)
						{
							if (visited[a][b] == cnt)
							{
								map[a + min_length][b] = map[a][b];
								map[a][b] = '.';
								visited[a][b] = 0;
							}
						}
					}
					return;
				}
				cluster.clear();


				cnt++;
			}
		}
	}
	
}



int main()
{
	cin >> r >> c;
	for (int i = 0; i < r; i++)
	{
		string tmp1;
		cin >> tmp1;
		for (int j = 0; j < c; j++)
		{
			map[i][j] = tmp1[j];
		}

	}
	cin >> n;
	for (int a = 0; a < n; a++)
	{
		int tmp;
		cin >> tmp;
		//홀수면 왼쪽, 짝수면 오른쪽
		// 1) 부셔지는게 있나 찾기
		// 있으면 부셔
		if (a % 2 == 0)
		{
			for (int i = 0; i < c; i++)
			{
				if (map[r - tmp][i] == 'x')
				{
					map[r - tmp][i] = '.';
					break;
				}
			}
		}
		else
		{
			for (int i =c-1; i >= 0; i--)
			{
				if (map[r - tmp][i] == 'x')
				{
					map[r - tmp][i] = '.';
					break;
				}
			}
		}

		// 2) 떠있는 클러스터 있나 확인
		check_map();

	}


	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < c; j++)
		{
			cout << map[i][j];
		}
		cout << endl;
	}
	return 0;
}

'c++ > Baekjoon Online' 카테고리의 다른 글

백준 1765 : 닭싸움 팀 정하기 C++  (0) 2021.09.12
백준 11967 : 불켜기 C++  (0) 2021.09.12
백준 6198 : 옥상 정원 c++ (monotone stack)  (0) 2021.07.01
백준 2258 : 정육점 c++  (0) 2021.07.01
백준 1461 : 도서관 C++  (0) 2021.06.27