列表

详情


NC237065. 骑士战胜魔王

描述

牛牛在玩一款模拟游戏。

地图是一个由  三种字符组成的大小为  的方格图,其中 '.' 代表空格(空格可以被占据)、 代表城墙(城墙不可被通过)、 代表一个普通骑士,初始时每个普通骑士都单独占据了地图上自己所在的那一个格子。

每隔一秒,所有骑士都会进行一轮拓展。每轮拓展,骑士将会把和自己已经占据的格子相邻(这里的“相邻”指代两个格子具有共用边,下同且未被其它骑士占领的格子给占据。若在一轮拓展中,有多个骑士想占据同一个未被占据的格子,那么这个格子将会被这些骑士里初始坐标中横坐标最小的骑士占据,若初始坐标中横坐标最小的骑士有多个则这个格子会被横坐标最小的骑士中纵坐标最小的骑士所占据(这样的骑士只有一个)。

游戏开始时牛牛可以指定若干个普通骑士赋予他们圣光,将他们进阶为圣光骑士,但圣光不能改变骑士们拓展领域的规则。

游戏中有一个大魔王,它会从地图的左上角(既编号为 (1,1) 的格子)向位于右下角(既编号为 (n, m) 的格字)的村庄侵蚀过去(通过相邻且可以到达的格子),魔王的侵蚀速度可以认为是无穷大(瞬间即可到达(如果可以到达的话))的,魔王可以通过普通骑士所占据的格子但是不能通过被圣光骑士所占据的格子。

圣光骑士需要保护村庄(不让魔王到达村庄),牛牛想知道为了阻止魔王侵蚀村庄,至少需要多久的时间给骑士进行防守(占据格子),且在时间最短的前提下至少需要给几个骑士赋予圣光。

输入描述

输入第一行两个整数 n,m 。
接下来输入一个  的字符矩阵,描述整个地图。
保证:

输出描述

输出共一行两个整数分别代表骑士防守需要的最小时间以及在时间最小化的前提下最少需要给几个骑士赋予圣光。
特别的,如果无法封锁魔王通往村庄的道路则输出 -1

示例1

输入:

6 7
.......
...#.*.
..##..*
....*..
.*.#.#.
...*...

输出:

1 2

说明:

一秒钟后通过初始坐标在:(2,6) 和 (5,2) 的点就可以封锁掉魔王通向村庄的道路。

示例2

输入:

3 3
#.#
.#.
#.#

输出:

0 0

说明:

若魔王的入口或村庄的入口被封锁,或者魔王不存在能够通向村庄的路,则骑士不需要拓展就可以阻止魔王。
图中测试案例中可能不存在骑士。

示例3

输入:

3 3
*..
...
..*

输出:

0 1

说明:

只需要将 (1,1) 或 (3,3) 位置的骑士进阶为圣光骑士就可以阻断魔王的路了。

示例4

输入:

5 5
.....
..#..
.#*#.
..#..
.....

输出:

-1

说明:

不论经过多久骑士都不可能阻断魔王的通路。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 2768ms, 内存消耗: 14908K, 提交时间: 2022-09-22 23:57:56

#include<bits/stdc++.h>
using namespace std;
int main()
{
	ios_base::sync_with_stdio(false);
	int n,m;
	cin>>n>>m;
	vector<string> s(n+5);
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		s[i]=' '+s[i];
	}
	auto hs=[&](int x,int y)
	{
		return (x-1)*m+y;
	};
	const array<int,8> dx={1,0,-1,0,1,1,-1,-1},dy={0,1,0,-1,1,-1,1,-1};
	auto inbounds=[&](int x,int y)
	{
		return 1<=x and x<=n and 1<=y and y<=m;
	};
	auto cal=[&](int t,int fl=0)
	{
		vector<vector<int>> dis(n+5,vector<int>(m+5,1e9)),col(n+5,vector<int>(m+5));
		queue<pair<int,int>> q;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(s[i][j]=='*')
				{
					dis[i][j]=0;
					col[i][j]=hs(i,j);
					if(dis[i][j]<t)q.emplace(i,j);
				}
			}
		}
		while(not q.empty())
		{
			auto [x,y]=q.front();q.pop();
			for(int d=0;d<4;d++)
			{
				if(inbounds(x+dx[d],y+dy[d]) and s[x+dx[d]][y+dy[d]]!='#' and dis[x+dx[d]][y+dy[d]]>dis[x][y]+1)
				{
					dis[x+dx[d]][y+dy[d]]=dis[x][y]+1;
					col[x+dx[d]][y+dy[d]]=col[x][y];
					if(dis[x+dx[d]][y+dy[d]]<t)q.emplace(x+dx[d],y+dy[d]);
				}
			}
		}
		if(fl)
		{
			fill(dis.begin(),dis.end(),vector<int>(m+5,1e9));
			const int lim=n+m;
			vector<queue<pair<int,int>>> pq(lim+5);
			for(int i=1;i<=n;i++)
			{
				if(s[i][1]=='#')
				{
					dis[i][1]=0;
					pq[0].emplace(i,1);
				}
				else if(col[i][1])
				{
					dis[i][1]=1;
					pq[1].emplace(i,1);
				}
			}
			for(int i=1;i<=m;i++)
			{
				if(s[n][i]=='#')
				{
					dis[n][i]=0;
					pq[0].emplace(n,i);
				}
				else if(col[n][i])
				{
					dis[n][i]=1;
					pq[1].emplace(n,i);
				}
			}
			int cd=0;
			while(cd<=lim)
			{
				while(pq[cd].empty() and cd<=lim)cd++;
				if(cd>lim)break;
				auto [x,y]=pq[cd].front();pq[cd].pop();
				if(dis[x][y]!=cd)continue;
				for(int d=0;d<8;d++)
				{
					int xx=x+dx[d],yy=y+dy[d];
					if(inbounds(xx,yy) and (s[xx][yy]=='#' or col[xx][yy]))
					{
						int del;
						if(s[xx][yy]=='#' and s[x][y]=='#')del=0;
						else if(s[xx][yy]=='#' or s[x][y]=='#')del=1;
						else if(col[xx][yy]==col[x][y])del=0;
						else del=2;
						if(dis[xx][yy]>dis[x][y]+del)
						{
							dis[xx][yy]=dis[x][y]+del;
							pq[dis[xx][yy]].emplace(xx,yy);
						}
					}
				}
			}
			int ans=1e9;
			for(int i=1;i<=n;i++)
			{
				if(s[i][m]=='#')
					ans=min(ans,dis[i][m]);
				else if(col[i][m])
					ans=min(ans,dis[i][m]+1);
			}
			for(int i=1;i<=m;i++)
			{
				if(s[1][i]=='#')
					ans=min(ans,dis[1][i]);
				else if(col[1][i])
					ans=min(ans,dis[1][i]+1);
			}
			return ans/2;
		}
		else
		{
			fill(dis.begin(),dis.end(),vector<int>(m+5,1e9));
			queue<pair<int,int>> q;
			for(int i=1;i<=n;i++)
			{
				if(s[i][1]=='#' or col[i][1])
				{
					dis[i][1]=0;
					q.emplace(i,1);
				}
			}
			for(int i=1;i<=m;i++)
			{
				if(s[n][i]=='#' or col[n][i])
				{
					dis[n][i]=0;
					q.emplace(n,i);
				}
			}
			while(not q.empty())
			{
				auto [x,y]=q.front();q.pop();
				for(int d=0;d<8;d++)
				{
					int xx=x+dx[d],yy=y+dy[d];
					if(inbounds(xx,yy) and (s[xx][yy]=='#' or col[xx][yy]))
					{
						int del=0;
						if(dis[xx][yy]>dis[x][y]+del)
						{
							dis[xx][yy]=dis[x][y]+del;
							q.emplace(xx,yy);
						}
					}
				}
			}
			int ans=1e9;
			for(int i=1;i<=n;i++)
			{
				if(s[i][m]=='#')
					ans=min(ans,dis[i][m]);
				else if(col[i][m])
					ans=min(ans,dis[i][m]+1);
			}
			for(int i=1;i<=m;i++)
			{
				if(s[1][i]=='#')
					ans=min(ans,dis[1][i]);
				else if(col[1][i])
					ans=min(ans,dis[1][i]+1);
			}
			return ans/2;
		}
	};
	int l=0,r=n*m;
	while(l<r)
	{
		int mid=(l+r)/2;
		if(cal(mid)<=n*m)r=mid;
		else l=mid+1;
	}
	if(l!=n*m)cout<<l<<' '<<cal(l,1)<<endl;
	else cout<<-1<<endl;
	return 0;
}

上一题