[USACO20DEC] Stuck in a Rut S

洛谷题面

良心模拟题!!!

题目大意

无限大的网格图上有 \(N\) 头奶牛,第 \(i\) 头奶牛的坐标为 \((x_i,y_i)\),一些奶牛朝向北面,一些奶牛朝向东面。

每一小时,若奶牛遇到了一个没有被吃过草的格子,她会吃掉当前这一格的全部草,并向前走一步;否则它会在这一格停住,不再往前走。特别地,若两头奶牛同时到达某一格子,它们会分享这个格子的草,并继续向前走。

我们称奶牛 \(a\) 阻碍了奶牛 \(b\) 当且仅当 \(b\) 到达了一个 \(a\) 已经吃过草的格子而停下,而「阻碍」关系具有传递性,即若 \(a\) 阻碍了 \(b\),且 \(b\) 阻碍了 \(c\),那么我们认为 \(a\) 也阻碍了 \(c\)

现在要求求出每头奶牛阻碍的奶牛数量。

题目分析

\(a\) 会遇到牛 \(b\) 走过的方格,有两种情况:

  • \(way[a]=N,way[b]=E,x[a]>x[b],y[a]<y[b]\)

  • \(way[a]=E,way[b]=N,x[a]<x[b],y[a]>y[b]\)

于是我们将所有满足条件的 \(a,b\) 放到结构体 \(tmp\) 中。

\(tmp\) 中,我们存储了所有奶牛的交点:

\(id1,id2\) 分别存满足条件的 \(\verb!East!\) 奶牛和 \(\verb!North!\) 奶牛的下标;

\(x,y\) 则表示交点坐标。

随后将这些交点从左往右排序。

最后,再遍历依次数组得到答案。

具体地:

(下面记向东方走的奶牛为东方奶牛,向北方走的奶牛为北方奶牛)

\(|tmp[i].x-x[east]|>|tmp[i].y-y[north]|\),代表交点距离北方奶牛的距离更近一些,于是将 \(ans[north]\) 加上 \(ans[east]+1\)

另一种离东方奶牛的距离更近的情况同理。


时间复杂度 \(\mathcal{O}(n^2)\)

代码

const int ma=1005;

struct Node
{
	char opt;
	
	int x,y;
	
	int ans;
};

Node node[ma];

struct Answer
{
	int id1,id2;//id1 存 East,id2 存 North 
	
	int x,y;
};

Answer tmp[ma*ma];

bool vis[ma];

int n;

int idx;

inline bool cmp(Answer x,Answer y)
{
	if(x.x!=y.x)
	{
		return x.x<y.x;
	}
	
	return x.y<y.y;
}

inline int Abs(int x)
{
	return x>0?x:-x;
}

int main(void)
{
	speed_up();
	
	n=read();
	
	for(register int i=1;i<=n;i++)
	{
		cin>>node[i].opt;
		
		node[i].x=read(),node[i].y=read();
	}
	
	for(register int i=1;i<=n;i++)
	{
		for(register int j=i+1;j<=n;j++)
		{
			if(node[i].opt=='E' && node[j].opt=='N' && node[i].x<node[j].x && node[i].y>node[j].y)
			{
				tmp[++idx].x=node[j].x,tmp[idx].y=node[i].y;
				
				tmp[idx].id1=i,tmp[idx].id2=j;
			}
			
			else if(node[i].opt=='N' && node[j].opt=='E' && node[i].x>node[j].x && node[i].y<node[j].y)
			{
				tmp[++idx].x=node[i].x,tmp[idx].y=node[j].y;
				
				tmp[idx].id1=j,tmp[idx].id2=i;
			}
		}
	}
	
	sort(tmp+1,tmp+idx+1,cmp);
	
//	for(register int i=1;i<=idx;i++)
//	{
//		printf("%d %d %d %d\n",tmp[i].id1,tmp[i].id2,tmp[i].x,tmp[i].y);
//	}
	
	for(register int i=1;i<=idx;i++)
	{
		int east=tmp[i].id1,north=tmp[i].id2;
		
		if(vis[east]==false && vis[north]==false)
		{
			if(Abs(tmp[i].x-node[east].x)>Abs(tmp[i].y-node[north].y))
			{
				vis[east]=true;
				
				node[north].ans+=node[east].ans+1;	
			}
			
			else if(Abs(tmp[i].x-node[east].x)<Abs(tmp[i].y-node[north].y))
			{
				vis[north]=true;
				
				node[east].ans+=node[north].ans+1;
			}
		}
	}
	
	for(register int i=1;i<=n;i++)
	{
		printf("%d\n",node[i].ans);
	}
	
	return 0;
}
posted @ 2021-12-25 12:59  Coros_Trusds  阅读(123)  评论(0编辑  收藏  举报