7250. 【USACO 2020 December Contest, Gold】Replication

Description&&Data Constraint

Solution

首先我们可以求出每个点距离最近的岩石的距离,来判断能否走到这个点。

同时因为机器人可以放置在任何一个起始位置,所以对于每个不是岩石或者起始点的点,可以求出它到最近的起始点的距离,来表示初始机器人走到那个点的时间。

但走的时候要注意,只有能走到才能走。

就是说如果到达这个点的时候,副本机器人撞到岩石了,那么这个点就不能继续往下扩展了。

那么什么情况下是无法到达呢?

现在我们已经知道了当前点距离最近的起点的距离,那么就可以算出产生出来的副本距离当前点的曼哈顿距离,也就是 (lfloor dfrac{dis_{x,y}}{d} floor)

用这个去跟当前距离最近岩石的距离比较一下,如果大于等于距离最近岩石的距离,就说明副本机器人撞岩石了,就不用从这个点继续扩展了。

上面的两个都可以用 ( ext{bfs}) 来处理。

那么现在对于初始机器人可以直接走到的位置都已经处理出来了(即 (dis_{i,j}ge 0) 的位置),我们离解决这题只剩下求出副本机器人到的位置数量。

注:首先避免重复,可以把算过的位置打上标记。

这里我们考虑将 ( ext{bfs}) 的方式调转一下,对于初始机器人能到达的位置,从这个位置往外扩展来走到副本机器人能走到的位置。

而这个向外走的距离,要么是到达此点时复制机器人的次数,或者是到最近的岩石距离减去 1,代表着岩石与当前位置之间的空位。

但此时的队列并不一定满足单调,所以要将队列转成优先队列来模拟大根堆。

Code

#include<queue>
#include<cstdio>
#include<cstring>
#define N 1005
using namespace std;
struct node
{
	int x,y,dis;
};
struct node1
{
	int x,y,dis;
	friend bool operator <(const node1 &X,const node1 &Y) {return X.dis<Y.dis;}
};
queue<node> q_rock,q_robot;
priority_queue<node1> getans;
int n,d,ans,fx[5]={0,1,-1,0,0},fy[5]={0,0,0,1,-1},a[N][N],torock[N][N],frorobot[N][N];
bool bj[N][N];
char s[N];
int main()
{
	memset(torock,-1,sizeof(torock));
	memset(frorobot,-1,sizeof(frorobot));
	scanf("%d%d",&n,&d);
	for (int i=1;i<=n;++i)
	{
		scanf("%s",s+1);
		for (int j=1;j<=n;++j)
		{
			if (s[j]=='#')
			{
				a[i][j]=1;
				node x;
				x.x=i;x.y=j;x.dis=0;
				q_rock.push(x);
				torock[i][j]=0;
			}
			if (s[j]=='S')
			{
				a[i][j]=1;
				node x;
				x.x=i;x.y=j;x.dis=0;
				q_robot.push(x);
				frorobot[i][j]=0;
			}
		}
	}
	while (!q_rock.empty())
	{
		node u=q_rock.front();q_rock.pop();
		for (int i=1;i<=4;++i)
		{
			int xx=u.x+fx[i],yy=u.y+fy[i];
			if (torock[xx][yy]<0&&xx>=1&&yy>=1&&xx<=n&&yy<=n)
			{
				torock[xx][yy]=u.dis+1;
				node x;
				x.x=xx;x.y=yy;x.dis=u.dis+1;
				q_rock.push(x);
			}
		}
	}
	while (!q_robot.empty())
	{
		node u=q_robot.front();q_robot.pop();
		if (u.dis/d>=torock[u.x][u.y]) continue;
		for (int i=1;i<=4;++i)
		{
			int xx=u.x+fx[i],yy=u.y+fy[i];
			if (frorobot[xx][yy]<0&&u.dis/d<torock[xx][yy]&&!a[xx][yy])
			{
				frorobot[xx][yy]=u.dis+1;
				node x;
				x.x=xx;x.y=yy;x.dis=u.dis+1;
				q_robot.push(x);
			}
		}
	}
	for (int i=1;i<=n;++i)
		for (int j=1;j<=n;++j)
			if (frorobot[i][j]>=0)
			{
				node1 x;
				x.x=i;x.y=j;x.dis=min(frorobot[i][j]/d,torock[i][j]-1);
				getans.push(x);
				bj[i][j]=true;
				++ans;
			}
	while (!getans.empty())
	{
		node1 u=getans.top();getans.pop();
		if (!u.dis) continue;
		for (int i=1;i<=4;++i)
		{
			int xx=u.x+fx[i],yy=u.y+fy[i];
			if (!bj[xx][yy]&&!a[xx][yy])
			{
				bj[xx][yy]=true;
				node1 x;
				x.x=xx;x.y=yy;x.dis=u.dis-1;
				getans.push(x);
				++ans;
			}
		}
	}
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/Livingston/p/15167015.html