7250. 【USACO 2020 December Contest, Gold】Replication
阿新 • • 發佈:2021-08-20
Description&&Data Constraint
Solution
首先我們可以求出每個點距離最近的岩石的距離,來判斷能否走到這個點。
同時因為機器人可以放置在任何一個起始位置,所以對於每個不是岩石或者起始點的點,可以求出它到最近的起始點的距離,來表示初始機器人走到那個點的時間。
但走的時候要注意,只有能走到才能走。
就是說如果到達這個點的時候,副本機器人撞到岩石了,那麼這個點就不能繼續往下擴充套件了。
那麼什麼情況下是無法到達呢?
現在我們已經知道了當前點距離最近的起點的距離,那麼就可以算出產生出來的副本距離當前點的曼哈頓距離,也就是 \(\lfloor \dfrac{dis_{x,y}}{d}\rfloor\)
用這個去跟當前距離最近岩石的距離比較一下,如果大於等於距離最近岩石的距離,就說明副本機器人撞岩石了,就不用從這個點繼續擴充套件了。
上面的兩個都可以用 \(\text{bfs}\) 來處理。
那麼現在對於初始機器人可以直接走到的位置都已經處理出來了(即 \(dis_{i,j}\ge 0\) 的位置),我們離解決這題只剩下求出副本機器人到的位置數量。
注:首先避免重複,可以把算過的位置打上標記。
這裡我們考慮將 \(\text{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\n",ans); return 0; }