巧虎机器人——颜色识别编程模式一

【问题描述】

以下图(a)所示的巧虎机器人还可以识别地图上方格的颜色(红色、绿色、蓝色、黄色这四种颜色之一,图(b)为地图示例),因此它还有一种复杂的编程模式——颜色识别编程模式:可以指定每种颜色对应的指令,假设有四种指令,即向北、向东、向南、向西走一个方格,每种颜色对应且只对应一种指令,然后在地图上指定一个起始位置和目标位置,问是否存在一种指令方案(即指定红色、绿色、蓝色、黄色分别代表四种指令之一),使得能从起始位置出发到达目标位置。到达目标位置后,巧虎机器人就停下来,不再执行目标位置方格颜色对应的指令。

A-a.png

(a) 巧虎机器人

B-b.png

(b) 地图示例

【输入形式】

输入文件包含多个测试数据,每个测试数据包含3部分,第1部分占一行,为两个整数,M N(用空格隔开),2<M, N<=20,表示地图的行和列(行号和列号均从1开始计起);第2部分也占一行,为四个整数,si sj di dj(用空格隔开),分别表示起始位置的行号和列号、目标位置的行号和列号;第3部分占M行,每行有N个字符,这些字符可能为:r, g, b, y,分别表示方格的颜色为红色、绿色、蓝色、黄色。以上图(b)就是第2个样例数据对应的地图。

输入文件最后一行为“0 0”,代表输入结束。

测试数据保证起始位置和目标位置有效且不是同一个位置。

注意,如果巧虎机器人到了边界上的某方格再执行该方格颜色对应的指令后出边界了,这视为失败,即当前指令方案不能使得从起始位置出发到达目标位置。

【输出形式】

对于每个测试数据,输出占一行,如果有这样一条路径可以从起点走到终点,则输出yes否则输出no

【样例输入】

5 5

1 3 4 5

rbybb

brrry

gbgyg

rgbyg

rbygb

5 5

1 2 4 3

rbybb

brrry

gbgyg

rgbyg

rbygb

0 0

【样例输出】

no

yes
思路:枚举24种可能的颜色搭配(4!=24)。类似于逃出迷宫,前进一步之后后路即被封死。所以我们这里采用沉岛法。
(直接把枚举结果贴出来方便理解)
Code:

#include<iostream>
#include<algorithm>
using namespace std;
//方向修改标志
int directionx[4] = { -1,0,1,0 };
int directiony[4] = { 0,1,0,-1 };
int m, n;//行和列
char Edge[25][25];//读取的矩阵
int flag;//逃脱成功的标志
//枚举所有颜色搭配的可能,共有4!=24种
int MEIJU[24][4] = {
	{0,1,2,3},{0,1.3,2},{0,2,1,3},{0,2,3,1},{0,3,2,1},{0,3,1,2},
	{1,0,2,3},{1,0,3,2},{1,2,0,3},{1,2,3,0},{1,3,0,2},{1,3,2,0},
	{2,0,1,3},{2,0,3,1},{2,1,0,3},{2,1,3,0},{2,3,1,0},{2,3,0,1},
	{3,0,1,2},{3,0,2,1},{3,2,0,1},{3,2,1,0},{3,1,0,2},{3,1,2,0}
};
//四种方向
int dong,nang,xi,bei;
//迷宫——沉岛法,寻找唯一逃生路径
void dfs(int si, int sj, int di, int dj) {
	if (si == di && sj == dj) {
		flag = true;
		return;
	}
	if (Edge[si][sj] == 'r') {
		int ni = si + directionx[bei];

		int nj = sj + directiony[bei];
		if (Edge[ni][nj]!='*'&&(ni > 0 && ni <= m) && (nj > 0 && nj <= n)) {
			//封住后路
			Edge[si][sj] = '*';
			//前进到下一步
			dfs(ni, nj, di, dj);
			//还原
			Edge[si][sj] = 'r';
		}
	}
	else if (Edge[si][sj] == 'b'){
		int ni = si + directionx[dong];

		int nj = sj + directiony[dong];
		if (Edge[ni][nj] != '*' && (ni > 0 && ni <= m) && (nj > 0 && nj <= n)) {
			//封住后路
			Edge[si][sj] = '*';
			//前进到下一步
			dfs(ni, nj, di, dj);
			//还原
			Edge[si][sj] = 'b';
		}
	}
	else if (Edge[si][sj] == 'y') {
		int ni = si + directionx[xi];

		int nj = sj + directiony[xi];
		if (Edge[ni][nj] != '*' && (ni > 0 && ni <= m) && (nj > 0 && nj <= n)) {
			//封住后路
			Edge[si][sj] = '*';
			//前进到下一步
			dfs(ni, nj, di, dj);
			//还原
			Edge[si][sj] = 'y';
		}
	}
	else {
		int ni = si + directionx[nang];

		int nj = sj + directiony[nang];
		if (Edge[ni][nj] != '*' && (ni > 0 && ni <= m) && (nj > 0 && nj <= n)) {
			//封住后路
			Edge[si][sj] = '*';
			//前进到下一步
			dfs(ni, nj, di, dj);
			//还原
			Edge[si][sj] = 'g';
		}
	}
}
int main() {
	while (true)
	{
		flag = false;
		memset(Edge, 0, sizeof(Edge));
		cin >> m >> n;
		if (m == 0 && n == 0)
			break;
		int si, sj, di, dj;
		cin >> si >> sj >> di >> dj;
		for (int i = 1; i <= m; i++)
		{
			for (int j = 1; j <= n; j++) {
				cin >> Edge[i][j];
			}
		}
		for (int i = 0; i < 24; i++) {
			dong = MEIJU[i][0];
			nang = MEIJU[i][1];
			xi = MEIJU[i][2];
			bei = MEIJU[i][3];
			dfs(si, sj, di, dj);
		}
		if (flag)cout << "yes" << endl;
		else cout << "no" << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值