[白準C++2573氷山
質問する
地球温暖化で北極氷山が溶けている.図1に示すように、氷山を2次元アレイに表示します.氷山の各部分の高さ情報は,配列された各セルに正の整数として格納される.氷山以外の海に対応する格には0が格納されている.図1では、スペースはすべてゼロで埋め込まれていると思います.
図1.行数5、列数7の2 Dアレイの氷山の高さ情報を格納します.
氷山の高さは海水との接触が多い場所でより速く減少するため、配列中の氷山の各部分に対応する格子の高さは毎年、格子の中で東西南北4方向に付着する0の格子の個数を減少させる.ただし、各セルに格納される高さは0より小さくなりません.海水は湖水のように氷山に囲まれているかもしれない.従って、図1の氷山は、図2に示すように1年後に変形する.
図3は、図1の氷山の2年後の変化を示す.2 D配列では,東西南北方向の格子が互いに接続されている.したがって、図2の氷山は1つであり、図3の氷山は3つに分かれている.
氷山が1つ与えられた場合、プログラムを作成して、この氷山が2つ以上分離された最初の時間(年)を求めます.図1の氷山について、答えは2です.全てが溶けるまで2つ以上離さないと、プログラムは0を出力します.
入力
1行目では、2つの整数NとMは、2次元配列の行数と列数を表すスペースで区切られます.NとMは3以上300以下である.次のN行では、各行の間にスペースがあり、M個の整数は配列の各行を表します.各グリッドの値は0以上10以下です.配列では、氷山が占める格の個数、すなわち1以上の整数が占める格の個数が10000以下である.配列の最初の行と最後の行と最後の列は常に0で埋め込まれます.
しゅつりょく
1行目は氷山分離の最初の時間(年)を出力する.氷山が溶けるまで分離していない場合は0を出力します.
https://www.acmicpc.net/problem/2573
に答える
1時間ごとに氷山の位置をベクトルでメモするのが便利です.
氷山が1枚であることを確認します=>BFS
氷山の1時間あたりの融解量=>氷山の位置上下左右の海の数
氷山は1時間ごとに溶ける.
これは実施手順を考慮する価値のある問題である.BFS問題にとって、難易度は高くない.これはBFSを適用して氷河が一つであるかどうかを判断する問題のようだ.詳細はコードにコメントを書きました.
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using std::vector; using std::pair; using std::queue;
typedef pair<int, int> pii;
/*
iceberg : 매시간마다 빙산높이를 저장
icebergList : 매시간마다 생존한 빙산좌표들
meltAmount : 매시간마다 빙하가 녹는양을 저장
visited : finished 함수에서 BFS로 사용하기위한 방문체크 배열
loc : finished 함수에서 빙산이 한덩어리인지 찾기위해
BFS를 사용하기위한 큐
hour : 현재시간, 출력값
dx, dy : 방향벡터
*/
int n, m, ** iceberg, ** meltAmount, hour = 0;
bool** visited;
vector<pii> icebergList;
queue<pii> loc;
int dx[4] = { 0, 1, 0, -1 };
int dy[4] = { 1, 0, -1, 0 };
bool findMeltAmount();
bool isOnePiece();
void melting();
void func();
void func() {
while (1) {
if (!findMeltAmount()) { //빙산이존재하지않으면 0출력, 종료
printf("0");
return;
}
if (!isOnePiece()) { //빙산이 둘이상으로 분리된경우 지난시간출력, 종료
printf("%d", hour);
return;
}
melting(); //빙산을 녹인다.
hour++;
}
}
//실제로 빙산을 녹인다.
void melting() {
for (int k = 0; k < icebergList.size(); k++) {
int x = icebergList[k].first;
int y = icebergList[k].second;
iceberg[x][y] -= meltAmount[x][y];
if (iceberg[x][y] < 0) iceberg[x][y] = 0; //0이하로 떨어지지않음
}
}
//빙산위치중 하나에서 시작해서 BFS로 한덩어리로 이루어졌는지 확인하는 함수
//두덩어리 이상으로 분리된경우 false 리턴
bool isOnePiece() {
int icebergCnt = icebergList.size();
int init_x = icebergList[0].first;
int init_y = icebergList[0].second;
loc.push({ init_x, init_y }); //BFS 시작위치
visited[init_x][init_y] = true; //방문체크
icebergCnt--; //빙산갯수카운트
while (!loc.empty()) {
int x = loc.front().first; //현재위치
int y = loc.front().second;
loc.pop();
for (int d = 0; d < 4; d++) {
int xx = x + dx[d]; //다음위치
int yy = y + dy[d];
//맵을벗어난경우 제외
if (xx < 0 || yy < 0 || xx == n || yy == m) continue;
//방문한적없고, 빙산이 존재하는곳이면 이동
if (!visited[xx][yy] && iceberg[xx][yy] > 0) {
visited[xx][yy] = true; //방문체크
loc.push({ xx, yy }); //다음위치를 큐에넣어서 탐색을이어감
icebergCnt--;
}
}
}
if (icebergCnt > 0) //모든 빙산이 이어져있지않은경우
return false;
else
return true;
}
//현재빙산이 녹는 속도를 계산
//빙산이없으면 false리턴
bool findMeltAmount() {
icebergList.clear();
for (int i = 0; i < n; i++)
for(int j = 0 ; j < m ; j++)
if (iceberg[i][j] != 0)
icebergList.push_back({ i, j }); //빙산위치를 기록
if (icebergList.size() == 0) return false;
//초기화 1
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
meltAmount[i][j] = 0;
//초기화 2
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
visited[i][j] = false;
//빙산마다 녹는속도를 계산
for (int k = 0; k < icebergList.size(); k++) {
int x = icebergList[k].first;
int y = icebergList[k].second;
int amount = 0;
for (int d = 0; d < 4; d++) {
int xx = x + dx[d];
int yy = y + dy[d];
if (xx < 0 || yy < 0 || xx == n || yy == m) continue;
if (iceberg[xx][yy] == 0) amount++; //4방향중 바다가있는곳
}
meltAmount[x][y] = amount;
}
return true;
}
int main(void) {
scanf("%d%d", &n, &m);
iceberg = new int* [n];
meltAmount = new int* [n];
visited = new bool* [n];
for (int i = 0; i < n; i++) {
iceberg[i] = new int[m];
meltAmount[i] = new int[m];
visited[i] = new bool[m];
for (int j = 0; j < m; j++) {
scanf("%d", &iceberg[i][j]);
}
}
func();
return 0;
}
Reference
この問題について([白準C++2573氷山), 我々は、より多くの情報をここで見つけました https://velog.io/@cldhfleks2/2573テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol