[USACO20DEC] Stuck in a Rut S
良心模擬題!!!
題目大意
無限大的網格圖上有 \(N\) 頭奶牛,第 \(i\) 頭奶牛的座標為 \((x_i,y_i)\),一些奶牛朝向北面,一些奶牛朝向東面。
每一小時,若奶牛遇到了一個沒有被吃過草的格子,她會吃掉當前這一格的全部草,並向前走一步;否則它會在這一格停住,不再往前走。特別地,若兩頭奶牛同時到達某一格子,它們會分享這個格子的草,並繼續向前走。
我們稱奶牛 \(a\) 阻礙了奶牛 \(b\) 當且僅當 \(b\) 到達了一個 \(a\) 已經吃過草的格子而停下,而「阻礙」關係具有傳遞性,即若 \(a\) 阻礙了 \(b\),且 \(b\) 阻礙了 \(c\),那麼我們認為 \(a\)
現在要求求出每頭奶牛阻礙的奶牛數量。
題目分析
牛 \(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; }