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

67 篇文章 1 订阅

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);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值