[白俊C+]14503ロボット掃除機
質問する
ロボット掃除機がある場合は、清掃領域の個数を計算するプログラムを作成してください.
ロボット掃除機があるところはNです×Mサイズの長方形として表示できます.×1サイズの正方形の格子に分けます.各格子は壁またはスペースです.掃除機は向きがあり、この方向は東、西、南、北の一つです.地図の各格は(r,c)と表すことができ、rは北から来た格の個数であり、cは西から来た格の個数である.
ロボット掃除機の動作原理は以下の通りです.
現在の位置をクリアします.
現在の位置で、隣接するセルを現在の方向に対して左から右に順に移動します.
左側方向にクリーンアップされていないスペースがある場合は、その方向に回転し、1番から1段進みます.
左方向に清掃スペースがなければ、その方向に回転して2番に戻ります.
4つの方向が清掃されているか壁がある場合は、見ている方向を1段後退させ、2番に戻ります.
4つの方向が清掃または壁で、後ろの方向が壁でバックできない場合は、作業を停止します.
ロボット掃除機は掃除した部屋を掃除しなくなり、壁を通ることができません.
入力
第1行は、縦方向サイズNおよび横方向サイズMを与える.(3 ≤ N, M ≤ 50)
2行目は、ロボット掃除機が位置するセルの座標(r,c)と向きdを示す.すなわち,dは0時に北へ,1時に東へ,2時に南へ,3時に西へである.
3行目からN行目では,場所の状態は北から南へ順に,各行は西から東へ順次であった.スペースは0、壁は1です.地図の最初の行、最後の行、最初の列、最後の列のすべてのセルは壁です.
ロボット掃除機のある部屋の状態はいつも空いています.
しゅつりょく
ロボット掃除機は清掃する車両数を出力します.
https://www.acmicpc.net/problem/14503
に答える
最初の問題のa~dは1つ1つの関数で実現され,時には繰り返し,最終的にはロボット()を1つの関数で全過程を繰り返す.
まず、方向(変数d)を変更する関数cd()を定義し、0、3、2、1、0、3...彼らを順番に変えさせます.
無限ループをwhile(true)で回転し、
毎回int dir=cd(d);現在の方向から左に開いた方向値をdirに保存
next関数を定義し、この場所の次の値が何であるかを表示します.
0(空きスペース)に遭遇した場合、実際に移動関数を実行して掃除機の位置を変更します.
説明が冗長すぎて、コードにコメントを残します.
具体的な数学過程と論理過程がなく、体現だけで問題を解決することができる.
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
int N, M, **house;
int r, c, d; //로봇위치, 방향 0)북 1)동 2)남 3)서
/*
0 : 청소하지않은공간
1 : 벽
2 : 청소함
*/
void clean(); //함수원형들
int cd(int dir);
int next(int dir);
void move(int dir);
bool f();
void clean() { //현재 로봇위치를 청소
if (house[r][c] != 2) {
house[r][c] = 2;
}
}
bool f() { //사방이 전부 막혔는가
if(next(d) != 0 &&
next(cd(d)) != 0 &&
next(cd(cd(d))) != 0 &&
next(cd(cd(cd(d)))) != 0) {
return true;
}
return false;
}
int cd(int dir) { //방향전환(반시계방향으로-왼쪽)
dir--;
if (dir == -1) dir = 3;
return dir;
}
//dir방향 1칸앞에 무엇이있는가
int next(int dir) {
//0) 청소하지않은공간
//1) 벽(이동불가, 배열범위를벗어난경우도 포함)
//2) 청소한공간
int now_r = r, now_c = c;
if (dir == 0) {
now_r--; //북
}
else if (dir == 1) {
now_c++; //동
}
else if (dir == 2) {
now_r++; //남
}
else if (dir == 3) {
now_c--; //서
}
if (now_r < 0 || now_r == N ||
now_c < 0 || now_c == M) {
return 1; //이동불가능한곳은 벽으로생각함
}
return house[now_r][now_c]; //상태(0,1,2)를 출력
}
//실제로 dir방향으로 움직이는 함수
void move(int dir) {
int now_r = r, now_c = c;
if (dir == 0) {
now_r--; //북
}
else if (dir == 1) {
now_c++; //동
}
else if (dir == 2) {
now_r++; //남
}
else if (dir == 3) {
now_c--; //서
}
r = now_r; //실제위치 기록
c = now_c;
}
void robot() {
while (true) {
clean(); //현재위치청소
int dir = cd(d); //왼쪽으로 한번돈다.
if (next(dir) == 0) {
//청소하지않은공간이라면
move(dir);
d = dir;
continue;
}
if (f()) { //사방이막힌경우
dir = cd(cd(d)); //두번돌리면 후진방향
if (next(dir) == 1) {
//뒤가 벽이었다면 후진불가하니 종료
return;
}
else {
//후진가능하면
move(dir); //후진
continue;
}
}
//벽이나 청소한곳이라면 방향만전환
d = dir;
}
}
void printAll() { //청소한 총 면적을 출력
int res=0;
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
if (house[i][j] == 2)
res++;
printf("%d", res);
}
int main(void) {
scanf("%d%d", &N, &M);
house = new int*[N];
for (int i = 0; i < N; i++)
house[i] = new int[M]; //맵생성
scanf("%d%d%d", &r, &c, &d);
for(int i = 0 ; i < N ; i++) //맵기록
for (int j = 0, temp=0; j < M; j++) {
scanf("%d", &temp);
house[i][j] = temp;
}
robot();
printAll();
return 0;
}
Reference
この問題について([白俊C+]14503ロボット掃除機), 我々は、より多くの情報をここで見つけました https://velog.io/@cldhfleks2/14503テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol