[伯俊C+]2636チーズ
質問する
下図1に示すように、正方形の格子からなる正方形の板があり、その上に薄いチーズ(灰色の部分)が置かれています.板の縁(<図1>では、四角形のXの部分)にはチーズが入っておらず、チーズには1つ以上の穴が開いていてもよい.
これらのチーズを空気中に入れると溶け、空気に触れる車両は1時間後に溶けます.チーズの穴には空気が入っていませんが、穴を囲むチーズが溶けて穴が開くと空気が穴に入ります.<図1>に示すように、チーズ孔を囲むチーズは溶けず、図2>に示すように、「c」と表記された部分だけが1時間後に溶けて消える.
<図1>オリジナルチーズ形状
あと1時間で<図2>の「c」で表される部分は<図3>に示すように溶けて消えてしまいます.
<図2>1時間後のチーズの形
<図3>2時間後のチーズの形
<図3>チーズが2時間後の様子で、残りの破片はあと1時間で全部溶けてしまいました.そのため、初めてチーズが全部溶けて消えるまで3時間かかります.<図3>に示すように、チーズは融解中にいくつかに分けることができる.
矩形板の大きさとチーズが板に置かれたとき、空気中のチーズがすべて溶けるのに要する時間と、すべて溶ける1時間前にチーズの破片が残った格子数を入力するプログラムを作成します.
入力
最初の行は、矩形板の縦横長が正の整数であることを示します.縦横の長さは最大100です.板上の各横線の形状は、上から下へ順に2行目から最後の行までです.チーズのない格子は0で、チーズのある格子は1で、数字の間にスペースがあります.
しゅつりょく
1行目はチーズが全部溶けて消えるまでの時間を出力し、2行目は全部溶ける1時間前に置いたチーズの破片の格子数を出力します.
https://www.acmicpc.net/problem/2636
に答える
問題は親切です.地図の端が空いているので、特別な設備はなく、チーズのないどこでBFSをしても答えが得られます.
BFSにculocと、チーズの位置を保存するboo[]chezeを用意し、アクセス位置を記録するbool[]アクセスを準備します.
ナビゲーション時には,地図上を上下左右に移動するためにdx,dyを用意する.
ナビゲーション中にチーズが見つかった場合は、キューに入れずにチーズを削除します.
チーズが見つからない場合にのみ、その位置をキューに入れて探索を続けます.
正直、BFSの概念を熟知していれば、銀色の問題があります.
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using std::queue; using std::pair;
typedef pair<int, int> pii;
/*
n,m : 맵크기
cheeze : 치즈위치 배열 true:치즈
visited : BFS에서 방문했는지 체크용
remainsCheeze = 방금전단계에서 남은 치즈
매단계마다 BFS 0,0부터 탐색, 탐색하며 치즈를 깎고, 탐색종료시
clear()실행
*/
int n, m, remainsCheeze=0, hour=1;
bool **cheeze, **visited;
int dx[4] = { 0, 1, 0, -1 };
int dy[4] = { 1, 0, -1, 0 };
void clear();
void init();
int countCheeze();
void DEBUG();
void func();
void func() {
queue<pii> loc;
while (remainsCheeze > 0) { //치즈가 한개라도 남은경우
loc.push({ 0,0 }); //0,0부터탐색
visited[0][0] = true;
while (!loc.empty()) {
int x = loc.front().first; //현재위치 (x,y)
int y = loc.front().second;
loc.pop();
//4방향으로탐색
for (int d = 0; d < 4; d++) {
int xx = x + dx[d]; //다음위치 (xx,yy)
int yy = y + dy[d];
//올바르지않은 범위
if (xx < 0 || yy < 0 || xx == n || yy == m)
continue;
if (!visited[xx][yy]) {
visited[xx][yy] = true;
if (cheeze[xx][yy]) //치즈가있다면 없앰
cheeze[xx][yy] = false;
else //치즈가 없다면 다음위치에서 탐색을 이어서 진행
loc.push({ xx, yy });
}
}
}
//탐색후 모두 초기화
clear();
//DEBUG(); //디버그용
if (countCheeze() == 0) //탐색후 치즈가 없는경우
break;
remainsCheeze = countCheeze();
hour++;
}
printf("%d\n%d", hour, remainsCheeze);
}
void DEBUG() {
printf("==================================%d 시간뒤\n", hour);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++)
printf("%2d", cheeze[i][j]);
printf("\n");
}
printf("=====================================\n");
}
int countCheeze() {
int res = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (cheeze[i][j]) res++;
return res;
}
void init() {
scanf("%d%d", &n, &m);
cheeze = new bool* [n];
visited = new bool* [n];
for (int i = 0; i < n; i++) {
cheeze[i] = new bool[m];
visited[i] = new bool[m];
for (int j = 0; j < m; j++) {
scanf("%d", &cheeze[i][j]);
visited[i][j] = false;
}
}
remainsCheeze = countCheeze(); //남은치즈 초깃값
}
void clear() {
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
visited[i][j] = false;
}
int main(void) {
init();
func();
return 0;
}
Reference
この問題について([伯俊C+]2636チーズ), 我々は、より多くの情報をここで見つけました https://velog.io/@cldhfleks2/2636テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol