[白俊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;
}