DFS水管工

本文介绍了如何利用深度优先搜索策略解决一个名为'水管工'的游戏问题。玩家需要在给定的N*M矩形土地上,通过旋转两种类型的水管(弯管和直管),从(1,1)连接到(N,M),避免树木区域。文章详细解析了如何从(1,1)开始尝试,通过尝试不同状态的水管来确保路径的连通性。并给出了具体的示例输入和输出,帮助理解算法的应用。" 119597600,10553591,源代码迁移至服务器指南,"['服务器管理', '代码部署', 'Tomcat', '云平台', '鲲鹏架构']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、规则
最近小哼又迷上一个叫做水管工的游戏。游戏的大致规则是这样的。一块矩形土地被分为N * M的单位正方形,现在这块土地上已经埋设有一些水管,水管将从坐标为(1,1)左上角左部边缘,延伸到(N,M)右下角右部边缘。水管只有2种,如下图所示。

在这里插入图片描述

每种管道将占据一个单位正方形土地。你现在可以旋转这些管道,使得构成一个管道系统,即创造一条从(1,1)到(N,M)的连通管道。标有树木的方格表示这里没有管道。如下图:一个5*4的土地中(2,4)处有一个树木。
在这里插入图片描述

我们可以旋转其中的一些管道,使之构成一个连通的管道系统,如下图。
在这里插入图片描述

如果通过旋转管道可以使之构成一个连通的管道系统,就输出铺设的路径,否则输出impossible。例如输入如下数据。

5 4
5 3 5 3
1 5 3 0
2 3 5 1
6 1 1 5
1 5 5 4
输出:

(1,1) (1,2) (2,2) (3,2) (3,3) (3,4) (4,4) (5,4)

输入的第一行为两个整数N和M(都不超过10),接下来的N行,每行有M个整数,表示地图中的每一小格。其中О表示树木,1~6分别表示管道的六种不同的摆放方式,如下图。

在这里插入图片描述

因为只有两种水管,一种是弯管一种是直管。弯管有4种状态,直管有2种状态。首先从(1,1)处开始尝试。(1,1)是直管,并且进水口在左边,因此(1,1)处的水管只能使用5号这种摆放方式,如下图。

在这里插入图片描述

之后达到(1.2)。(1.2)是弯管,进水口在左边,因此(1,2)的水管有2种摆放方式,分别是3号和4号。我们先尝试3号这种摆放方法〈其实摆放4号是不行的,因为会出界),之后到达(2,2),如下图。

在这里插入图片描述

#include<iostream>

using namespace std;

struct node{
	int x;
	int y;
};//用来记录经过点的坐标

static int a[15][15];
int book[15][15] = {0};
node root[15];//记录路径
int size;
static int N, M;
static int flag = 0;

static void dfs(int x, int y, int front){
	if (x == N - 1 && y == M){//这里的y值要注意,要超出图边界,水管要出水,出图
		flag = 1;
		for (int i = 0; i<size; ++i)
			cout <<"("<< root[i].x +1<<","<< root[i].y+1 <<")"<< " ";
		return;
	}
	if (x<0 || x >= N || y<0 || y >= M) return;//超过图边界return

	if (book[x][y]==1) return;//标记过return

	book[x][y] = 1;//标记

	root[size].x = x;//把经过的点放入路径栈
	root[size++].y = y;

	//水管口 左1 上2 右3 下4
	if (a[x][y] >= 5 && a[x][y] <= 6){//直的水管两种放置方式横放竖放
		if (front == 1)//水管口在左边
			dfs(x, y + 1, 1);//横放向右移动水管口在左边1
		if (front == 2)//水管口在上边
			dfs(x + 1, y, 2);//向下移动水管口在上边
		if (front == 3)//水管口在右边
			dfs(x, y - 1, 3);//水管口在右边
		if (front == 4)//水管口在下边
			dfs(x - 1, y, 4);    //水管口在下边                        
	}

	if (a[x][y] >= 1 && a[x][y] <= 4){//弯的水管
		if (front == 1){//类似 特别要注意一下下一次的水管口的位置
			dfs(x + 1, y, 2);
			dfs(x - 1, y, 4);
		}
		if (front == 2){
			dfs(x, y + 1, 1);
			dfs(x, y - 1, 3);
		}
		if (front == 3){
			dfs(x + 1, y, 2);
			dfs(x - 1, y, 4);
		}
		if (front == 4){
			dfs(x, y + 1, 1);
			dfs(x, y - 1, 3);
		}
	}
	book[x][y] = 0;
	if (size > 0) size--;
	return;
}

int main(int argc, char** argv)
{
	int test_case;
	int T;
	/*
	The freopen function below opens input.txt in read only mode and
	sets your standard input to work with the opened file.
	When you test your code with the sample data, you can use the function
	below to read in from the sample data file instead of the standard input.
	So. you can uncomment the following line for your local test. But you
	have to comment the following line when you submit for your scores.
	*/

	//freopen("input.txt", "r", stdin);
	cin >> T;

	/*
	Read each test case from standard input.
	*/
	for (test_case = 1; test_case <= T; ++test_case)
	{
		cin >> N >> M;
		for (int i = 0; i < N; i++){
			for (int j = 0; j < M; j++){
				a[i][j] = 0;
				book[i][j] = 0;
			}
			for (int i = 0; i < N; i++)
				for (int j = 0; j < M; j++)
					cin >> a[i][j];

			dfs(0, 0, 1);
			if (flag == 0)
				cout << "NO";
			else
				cout << "YES";
		}
		return 0;//Your program should return 0 on normal termination.
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CP3圣保罗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值