AGC004E - Salvage Robots
Solution
怎么又双叒叕遇到和NOIP2020T4NOIP2020T4NOIP2020T4和那道CFCFCF题一样的题了啊,惨痛回忆QAQQAQQAQ。
大概就是把问题看成刚开始的点不动,整个网格图动,机器人向上111格等于网格整体向下111格,左右同理。如果网格某一时刻有一部分在边界外面,就把那些部分切掉,然后把所有经过原点(EEE所在的点)的机器人都收集起来。
因此倘若我们向上、下、左、右分别移动了最多u,d,l,ru,d,l,ru,d,l,r格,那么现在的网格就是[d+1...n−u,r+1...m−l][d+1...n-u,r+1...m-l][d+1...n−u,r+1...m−l]范围内的,然后我们可以选择一个边界位置扩展出去,假设u+1u+1u+1,那么假设移动到了位置(u+1,y),y∈[l,r](u+1,y),y\in[l,r](u+1,y),y∈[l,r],显然对于所有y∈[max(r+1,l),min(m−l,r)]y\in [max(r+1,l),min(m-l,r)]y∈[max(r+1,l),min(m−l,r)],位置(u+1,y)(u+1,y)(u+1,y)上的机器人都可以被收集而不影响边界大小。这里要对边界取max/minmax/minmax/min是因为边界外的机器人都超出过边界消失了。
于是我们有了一个dpdpdp的思路:令fu,d,l,rf_{u,d,l,r}fu,d,l,r表示向上、下、左、右分别移动了最多u,d,l,ru,d,l,ru,d,l,r格最多收集的机器人。
每次可以从边界往外扩展一格,然后把那个边界上的机器人都加到新的状态里。预处理横纵方向的机器人个数前缀和即可O(1)O(1)O(1)转移。
时间复杂度O(n4)O(n^4)O(n4),空间也是O(n4)O(n^4)O(n4),空间256MB256MB256MB,只能开shortshortshort。
Code
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=1e9+7;
const int MAXN=101;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
int X,Y;
char st[MAXN];
short f[MAXN][MAXN][MAXN][MAXN],sl[MAXN][MAXN],su[MAXN][MAXN];
signed main()
{int n=read(),m=read();for (int i=1;i<=n;i++){scanf("%s",st+1);for (int j=1;j<=m;j++) {if (st[j]=='E') X=i,Y=j;if (st[j]=='o') sl[i][j]=su[i][j]=1;}}for (int i=1;i<=n;i++)for (int j=1;j<=m;j++) sl[i][j]+=sl[i][j-1],su[i][j]+=su[i-1][j];for (int u=0;u<X;u++)for (int d=0;d<=n-X;d++)for (int l=0;l<Y;l++)for (int r=0;r<=m-Y;r++) f[u][d][l][r]=-n*m;f[0][0][0][0]=0;short mx=0;for (int u=0;u<X;u++)for (int d=0;d<=n-X;d++)for (int l=0;l<Y;l++)for (int r=0;r<=m-Y;r++){if (X-(u+1)>=d+1) upmax(f[u+1][d][l][r],(short)(f[u][d][l][r]+sl[X-(u+1)][min(Y+r,m-l)]-sl[X-(u+1)][max(Y-l-1,r)]));if (X+(d+1)<=n-u) upmax(f[u][d+1][l][r],(short)(f[u][d][l][r]+sl[X+(d+1)][min(Y+r,m-l)]-sl[X+(d+1)][max(Y-l-1,r)]));if (Y-(l+1)>=r+1) upmax(f[u][d][l+1][r],(short)(f[u][d][l][r]+su[min(X+d,n-u)][Y-(l+1)]-su[max(X-u-1,d)][Y-(l+1)]));if (Y+(r+1)<=m-l) upmax(f[u][d][l][r+1],(short)(f[u][d][l][r]+su[min(X+d,n-u)][Y+(r+1)]-su[max(X-u-1,d)][Y+(r+1)]));upmax(mx,f[u][d][l][r]);}printf("%d\n",(int)mx);return 0;
}