【题解】牛客寒假基础算法训练营5 C 炫酷迷宫

题目链接在这里
鉴于有的读者可能看不到题目,这里我就复述一下,具体就是如果构造一个n*m的矩阵,使得从某两个点之间的最短距离为k。障碍用’x’表示,路用’.'表示。


怎么做呢,可以看出来,这又是一个构造的题目。
在矩阵里面,我们可以感受一下,曲折的路线是最长的,所以我们就构造曲折的路径,然后在构造好的图上跑一下bfs求一下距离为k的点在哪,输出就好啦!

至于为什么曲折的路线就是最长的, 还有没有更长的构造方法呢,其实笔者也不知道,但是这样写确实AC了,所以笔者猜测,曲折的构造就是最长的构造方法。

不过我们不知道横着还是竖着构造更好,我们就两种构造方法都试一下,然后我们在路径比较长的那个图上跑bfs就好啦。

下面是代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
char G1[maxn][maxn],G2[maxn][maxn],G[maxn][maxn];
bool vis[maxn][maxn];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int n,m,k;
struct node
{
	int x;
	int y;
	int stp;
};
void bfs(int x,int y)
{
	queue<node> q;
	q.push({x,y,0});
	vis[x][y] = 1;
	while(!q.empty())
	{
		node now = q.front();
		q.pop();
		if(now.stp==k)
		{
			printf("%d %d\n",now.x,now.y);
			return;
		}
		for(int i=0;i<4;i++)
		{
			int nx = now.x+dx[i];
			int ny = now.y+dy[i];
			if(nx>=1 && nx<=n && ny>=1 && ny<=m && !vis[nx][ny] && G[nx][ny]=='.')
			{
				vis[nx][ny] = 1;
				int nstp = now.stp+1;
				q.push({nx,ny,nstp});
			}
		}
	}
}
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	int cnt = 0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(i%2)
			{
				G1[i][j] = '.';
				cnt++;
			}
			else G1[i][j] = 'x';
		}
	}
	for(int i=2;i<=n;i+=4)
	{
		G1[i][m] = '.';
		cnt++;
	}
	for(int i=4;i<=n;i+=4)
	{
		G1[i][1] = '.';
		cnt++;
	}
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i%2)
			{
				G2[j][i] = '.';
				cnt--;
			}
			else G2[j][i] = 'x';
		}
	}
	for(int i=2;i<=m;i+=4)
	{
		G2[n][i] = '.';
		cnt--;
	}
	for(int i=4;i<=m;i+=4)
	{
		G2[1][i] = '.';
		cnt--;
	}
	if(cnt<0) 
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				G[i][j] = G2[i][j];
			}
		}
	}
	else
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				G[i][j] = G1[i][j];
			}
		}
	}
	printf("1 1\n");
	bfs(1,1);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			printf("%c",G[i][j]);
		}
		printf("\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值