小视野链接
洛谷链接
###题目大意
一个
n
∗
m
n*m
n∗m的网格上有一些黑点和一个出口。每次操作使所有黑点向上下左右中的任意一个方向移动一格。若移出边界则消失,移至出口则收集起来。问最终收集到的黑点数量最大值。
###题解
所有黑点的移动相当于出口和网格的移动,每动一下,相当于把某一行(列)去掉。
DP,设
f
[
i
]
[
j
]
[
k
]
[
l
]
f[i][j][k][l]
f[i][j][k][l]表示出口上下左右最多移动分别
i
,
j
,
k
,
l
i,j,k,l
i,j,k,l次的答案。转移方程见代码。边界为
f
[
0
]
[
0
]
[
0
]
[
0
]
=
0
f[0][0][0][0]=0
f[0][0][0][0]=0。注意判断剩余的行(列)是否大于移动的步数。
###代码
//#pragma GCC optimize(3)
#include<iostream>
#include<iomanip>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#define ll long long
#define db double
#define inf 101
#define INF (int)1e9
#define pi acos(-1)
#define rd(n) {n=0;char ch;int f=0;do{ch=getchar();if(ch=='-'){f=1;}}while(ch<'0'||ch>'9');while('0'<=ch&&ch<='9'){n=(n<<1)+(n<<3)+ch-48;ch=getchar();}if(f)n=-n;}
using namespace std;
int mp[inf][inf],sum[inf][inf],f[inf][inf][inf];
int n,m;
int getsum(int l1,int l2,int r1,int r2){
return sum[r1][r2]-sum[l1-1][r2]-sum[r1][l2-1]+sum[l1-1][l2-1];
}
int main(){
rd(n) rd(m)
char ch;
int ex,ey;
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
ch=getchar();
while (ch!='o' && ch!='.' && ch!='E'){
ch=getchar();
}
if (ch=='o'){
mp[i][j]=1;
}
else if (ch=='E'){
ex=i,ey=j;
}
}
}
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
sum[i][j]=mp[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
}
}
int ans=0;
for (int i=0;ex-i>=1;i++){
for (int j=0;ex+j<=n;j++){
int l1=max(ex-i,j+1),r1=min(ex+j,n-i);
if (l1>r1){
continue;
}
for (int k=0;ey-k>=1;k++){
for (int l=0;ey+l<=m;l++){
int l2=max(ey-k,1+l),r2=min(ey+l,m-k);
if (l2>r2){
continue;
}
ans=max(ans,f[j][k][l]);
if (i+j<n-ex){
f[j+1][k][l]=max(f[j+1][k][l],f[j][k][l]+getsum(ex+j+1,l2,ex+j+1,r2));
}
if (k+l<ey-1){
f[j][k+1][l]=max(f[j][k+1][l],f[j][k][l]+getsum(l1,ey-k-1,r1,ey-k-1));
}
if (k+l<m-ey){
f[j][k][l+1]=max(f[j][k][l+1],f[j][k][l]+getsum(l1,ey+l+1,r1,ey+l+1));
}
if (i+j<ex-1){
f[j][k][l]=max(f[j][k][l],f[j][k][l]+getsum(ex-i-1,l2,ex-i-1,r2));
}
}
}
}
}
printf("%d\n",ans);
return 0;
}