【国集作业】【AGC004E】Salvage Robots 【DP】

小视野链接
洛谷链接
###题目大意
一个 n ∗ m n*m nm的网格上有一些黑点和一个出口。每次操作使所有黑点向上下左右中的任意一个方向移动一格。若移出边界则消失,移至出口则收集起来。问最终收集到的黑点数量最大值。
###题解
所有黑点的移动相当于出口和网格的移动,每动一下,相当于把某一行(列)去掉。
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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值