[agc004e]Salvage Robots

本文介绍了一个网格图中多个机器人通过特定出口逃生的问题,并采用动态规划的方法来最大化获救机器人的数量。通过设定出口移动而非机器人移动,简化问题并设计状态转移方程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

本题的关键是想到让出口和矩形动,而不是机器人动,只要记录出口的位移矩形,便可以知道哪个区域的机器人已经飞出去了。

题目大意

一个网格图,有若干机器人,还有一个出口。
操作一系列指令让机器人上下左右,走出矩形就死,进入出口则得救。
最多救多少机器人?

DP

不妨认为矩形和出口会动。
我们设f[u,d,l,r]表示出口移动的上下左右,然后转移也很容易。
第一维可以省略,若如此做记得最后再执行往上的转移。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100+10;
int f[maxn][maxn][maxn],sum[maxn][maxn];
int i,j,k,l,r,u,d,t,n,m,ex,ey,ans,up,down,left,right;
char ch;
char get(){
    char ch=getchar();
    while (ch!='.'&&ch!='o'&&ch!='E') ch=getchar();
    return ch;
}
int getsum(int a,int b,int x,int y){
    return sum[x][y]-sum[a-1][y]-sum[x][b-1]+sum[a-1][b-1];
}
int main(){
    scanf("%d%d",&n,&m);
    fo(i,1,n)
        fo(j,1,m){
            ch=get();
            if (ch=='E'){
                ex=i;
                ey=j;
            }
            else if (ch=='o') sum[i][j]++;
        }
    fo(i,1,n)
        fo(j,1,m)
            sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
    fo(i,0,n)
        fo(j,0,m)
            fo(k,0,m)
                f[i][j][k]=-100000000;
    f[0][0][0]=0;
    fo(u,0,n){
        if (ex-u<1) break;
        fo(d,0,n){
            if (ex+d>n) break;
            up=max(ex-u,1+d);
            down=min(ex+d,n-u);
            if (up>down) continue;
            fo(l,0,m){
                if (ey-l<1) break;
                fo(r,0,m){
                    if (ey+r>m) break;
                    left=max(ey-l,1+r);
                    right=min(ey+r,m-l);
                    if (left>right) continue;
                    ans=max(ans,f[d][l][r]);
                    if (u+d<n-ex) f[d+1][l][r]=max(f[d+1][l][r],f[d][l][r]+getsum(ex+d+1,left,ex+d+1,right));
                    if (l+r<ey-1) f[d][l+1][r]=max(f[d][l+1][r],f[d][l][r]+getsum(up,ey-l-1,down,ey-l-1));
                    if (l+r<m-ey) f[d][l][r+1]=max(f[d][l][r+1],f[d][l][r]+getsum(up,ey+r+1,down,ey+r+1));
                    if (u+d<ex-1) f[d][l][r]=max(f[d][l][r],f[d][l][r]+getsum(ex-u-1,left,ex-u-1,right));
                }
            }
        }
    }
    printf("%d\n",ans);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值