1. 程式人生 > 其它 >[USACO20DEC] Stuck in a Rut S

[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;
}