您的位置:首页 > 其它

【JZOJ4930】【NOIP2017提高组模拟12.18】C

2016-12-20 15:46 459 查看

Description

给出一个H的行和W列的网格。第i行第j列的状态是由一个字母的A[i][j]表示,如下:

“.” 此格为空。

“o” 此格包含一个机器人。

“E” 此格包含一个出口,保证出口在整个网格中有且只有一个

每次可以选择上,下,左,右之一的方向,将所有剩余的机器人向这个方向移动一个格子,如果一个机器人被移出了网格,那么这个机器人会爆炸,并立即消失。如果一个机器人移动到出口所在的格子,机器人将获救,并消失,最多有多少机器人获救。

Data Constraint

对于20%的数据,n*m<=9

对于另外40%的数据,出口在网格图的最左上角,即第1行第1列。

对于100%的数据,n,m<=100

Solution

我们设f[l][r][u][d]表示起点E最多能覆盖到的范围。那么显然左边的r列是不能取的,右边的l列是不能取的,上边的d行是不能取的,下边的u行是不能取的,而能取到的范围为从E往左l列,往上u行,往右r列,往下d行的一个矩形。我们可以由f[l][r][u][d]转移至f[l+1][r][u][d]、f[l][r+1][u][d]、f[l][r][u+1][d]、f[l][r][u][d+1]时间复杂度为O(1/4N4),空间上开一下滚动后O(N3)。





Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=105;
int bz[maxn][maxn],g[maxn][maxn],p[maxn][maxn],f[2][maxn][maxn][maxn];
int n,m,i,t,j,k,l,s1,s2,ans,r,u,d,z,q;
char s[maxn];
int main(){
//freopen("data.in","r",stdin);
scanf("%d%d\n",&n,&m);
for (i=1;i<=n;i++){
scanf("%s\n",s+1);
for (j=1;j<=m;j++)
if (s[j]=='o') bz[i][j]=1;
else if (s[j]=='E') s1=i,s2=j;
}
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
g[i][j]=g[i][j-1]+bz[i][j],p[i][j]=p[i-1][j]+bz[i][j];
for (l=0;l<s2;l++){
q=1-q;
memset(f[1-q],0,sizeof(f[1-q]));
for (r=0;r<=m-s2;r++){
for (u=0;u<s1;u++)
for (d=0;d<=n-s1;d++){
if (s2-l-1>r) z=p[min(d+s1,n-u)][s2-l-1]-p[max(s1-u-1,d)][s2-l-1];
else z=0;
f[1-q][r][u][d]=max(f[1-q][r][u][d],f[q][r][u][d]+z);
if (m-l>r+s2) z=p[min(d+s1,n-u)][r+s2+1]-p[max(s1-u-1,d)][r+s2+1];
else z=0;
f[q][r+1][u][d]=max(f[q][r+1][u][d],f[q][r][u][d]+z);
if (s1-u-1>d) z=g[s1-u-1][min(s2+r,m-l)]-g[s1-u-1][max(r,s2-l-1)];
else z=0;
f[q][r][u+1][d]=max(f[q][r][u+1][d],f[q][r][u][d]+z);
if (n-u>d+s1) z=g[d+s1+1][min(s2+r,m-l)]-g[d+s1+1][max(r,s2-l-1)];
else z=0;
f[q][r][u][d+1]=max(f[q][r][u][d+1],f[q][r][u][d]+z);
ans=max(ans,f[q][r][u][d]);
}
}
}
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: