[DP记录]AT2045 [AGC004E] Salvage Robots

command_block

2021-04-21 19:35:48

Personal

**题意** : 有一个 $n\times m$ 的棋盘,上面有若干机器人,以及恰好一个出口。 每次可以命令所有机器人向上下左右中的某个方向移动一格,如果它超出了棋盘的边界就会消失。如果它到了出口的位置就会被你救下(并且从棋盘上消失)。 求能够救下的机器人的最大值。 $n,m\leq 100$ ,时限$\texttt{2s}$ ,空限$\texttt{250M}$。 ------------ 根据运动的相对性,可以看做机器人不动,而出口和棋盘一起移动。 记出口向上、左、下、右移动的最大距离分别 $w,a,s,d$ 。记出口位置为 $(x_0,y_0)$。 出口可以到达的区域为 $[x_0-w,x_0+s][y_0-a,y+d]$。 而且,矩形 $[1+s,n-w][1+d,m-a]$ 外的机器人若没有被拯救,必然已消失。 于是可以设计 $\rm DP$。设 $dp[w][a][s][d]$ 为出口向上、左、下、右移动的最大距离分别 $w,a,s,d$,已经拯救的最多机器人个数。 当 $w,a,s,d$ 其中一个扩大时,计算出扩大的部分(一条)与未消失部分的交集,即可计算能多拯救的机器人数目。 时空复杂度均为 $O(n^4)$ 。为了卡空间,使用 `short` 存储 $\rm DP$ 数组。 具体转移细节见代码。 ```cpp #include<algorithm> #include<cstdio> #define MaxN 105 using namespace std; short dp[MaxN][MaxN][MaxN][MaxN],o1[MaxN][MaxN],o2[MaxN][MaxN]; short qry1(int x,int l,int r) {return (l<=r) ? o1[x][r]-o1[x][l-1] : 0; } short qry2(int y,int l,int r) {return (l<=r) ? o2[r][y]-o2[l-1][y] : 0; } char s[MaxN][MaxN]; int n,m; int main() { scanf("%d%d",&n,&m); int x0,y0; for (int i=1;i<=n;i++){ scanf("%s",s[i]+1); for (int j=1;j<=m;j++){ o1[i][j]=(s[i][j]=='o')+o1[i][j-1]; o2[i][j]=(s[i][j]=='o')+o2[i-1][j]; if (s[i][j]=='E'){x0=i;y0=j;} } } short ans=0; for (int w=0;w<x0;w++) for (int a=0;a<y0;a++) for (int s=0;x0+s<=n;s++) for (int d=0;y0+d<=m;d++){ ans=max(ans,dp[w][a][s][d]); int lx=1+s,rx=n-w,ly=1+d,ry=m-a; if (w+1<x0){ int x1=x0-w-1,ly2=y0-a,ry2=y0+d; if (lx<=x1&&x1<=rx){ly2=max(ly2,ly);ry2=min(ry2,ry);} else {ly2=1;ry2=0;} dp[w+1][a][s][d]=max(dp[w+1][a][s][d],(short)(dp[w][a][s][d]+qry1(x1,ly2,ry2))); } if (a+1<y0){ int y1=y0-a-1,lx2=x0-w,rx2=x0+s; if (ly<=y1&&y1<=ry){lx2=max(lx2,lx);rx2=min(rx2,rx);} else {lx2=1;rx2=0;} dp[w][a+1][s][d]=max(dp[w][a+1][s][d],(short)(dp[w][a][s][d]+qry2(y1,lx2,rx2))); } if (x0+s<n){ int x1=x0+s+1,ly2=y0-a,ry2=y0+d; if (lx<=x1&&x1<=rx){ly2=max(ly2,ly);ry2=min(ry2,ry);} else {ly2=1;ry2=0;} dp[w][a][s+1][d]=max(dp[w][a][s+1][d],(short)(dp[w][a][s][d]+qry1(x1,ly2,ry2))); } if (y0+d<m){ int y1=y0+d+1,lx2=x0-w,rx2=x0+s; if (ly<=y1&&y1<=ry){lx2=max(lx2,lx);rx2=min(rx2,rx);} else {lx2=1;rx2=0;} dp[w][a][s][d+1]=max(dp[w][a][s][d+1],(short)(dp[w][a][s][d]+qry2(y1,lx2,rx2))); } } printf("%d",(int)ans); return 0; } ```