AGC 004 E Salvage Robots - dp

考虑设dp[a,b,c,d]表示E移动的历史最上左下右到哪里,以及对应的表示出(L,R,U,D)表示E目前最左右上下可以走到哪里,然后每次转移形如a–或b–或c++或d++,然后你发现只要能a–就能得到第a-1行[max(L,b),min(d,R)]的所有机器人,注意边界情况和内存。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#define gc getchar()
#define N 103
#define sint short
#define upd(x,y) (x=max(x,(short)(y)))
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
sint s[N][N],dp[N][N][N][N];char str[N][N];
inline sint S(int a,int b,int c,int d)
{
    if(a>c) swap(a,c);if(b>d) swap(b,d);
    return (short)(s[c][d]+s[a-1][b-1]-s[a-1][d]-s[c][b-1]);
}
int main()
{
    int n=inn(),m=inn(),x=0,y=0;sint ans=0;
    for(int i=1;i<=n;i++) scanf("%s",str[i]+1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(str[i][j]=='E') x=i,y=j;
            else s[i][j]=(str[i][j]=='o');
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
        s[i][j]=(short)(s[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1]);
    for(int a=x;a;a--) for(int b=y;b;b--)
        for(int c=x;c<=n;c++) for(int d=y;d<=m;d++)
        {
            ans=max(ans,dp[a][b][c][d]);int L=d-y+1,R=m-y+b,U=c-x+1,D=n-x+a;
            if(a>U) upd(dp[a-1][b][c][d],dp[a][b][c][d]+S(a-1,max(b,L),a-1,min(d,R)));
            if(b>L) upd(dp[a][b-1][c][d],dp[a][b][c][d]+S(max(a,U),b-1,min(c,D),b-1));
            if(c<D) upd(dp[a][b][c+1][d],dp[a][b][c][d]+S(c+1,max(b,L),c+1,min(d,R)));
            if(d<R) upd(dp[a][b][c][d+1],dp[a][b][c][d]+S(max(a,U),d+1,min(c,D),d+1));
        }
    return !printf("%d\n",(int)ans);
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/81873720
今日推荐