[AGC004E] Salvage Robots (DP)
Description
蛤蟆国的领土我们可以抽象为H*W的笼子,在这片蛤土上,有若干个机器人和一个出口,其余都是空地,每次蛤蟆会要求让所有的机器人向某个方向移动一步,当机器人移动到出口时会被蛤蟆活摘出来,当机器人移出笼子时会自焚,求你最多取出的多少个机器人。
Input
第一行两个整数H,W,如题目所述
接下来H行,每行W个字符,包含三类字符:
第一类是'.'表示空地
第二类是'o'表示有一个机器人
第三类是'E'表示有一个出口,出口有且仅有一个
题解:
这看起来就像是一道dp题……(我TM没想出来)
我们用 \(f[i][j][k][l]\) 表示我们已经把左上角为 \((i,j)\),右下角为 \((k,l)\) 的机器人都去掉了,最多能取多少个。
那我们状态转移的时候加入一行或者一列。
那我们要往上拓展一行时,就要看出口上方矩阵的高度要比底部剩余的高度要小才能把这些机器人都收入囊中,新加的那行的宽度就为左右剩余空格的最大值……
CODE:
#include<iostream>
#include<cstdio>
using namespace std;
char map[105][105];
int n,m,x,y,ans=0,a[105][105],b[105][105];
short f[105][105][105][105];
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",map[i]+1);
for(int j=1;j<=m;j++){
a[i][j]=a[i][j-1]+(map[i][j]=='o');
b[i][j]=b[i-1][j]+(map[i][j]=='o');
if(map[i][j]=='E')x=i,y=j;
}
}
for(int i=x;i>=1;i--)
for(int j=y;j>=1;j--){
for(int k=x;k<=n;k++)
for(int l=y;l<=m;l++){
if(i>1&&i-1>k-x)ans=max(ans,f[i-1][j][k][l]=max(f[i-1][j][k][l],f[i][j][k][l]+a[i-1][min(l,m-y+j)]-a[i-1][max(j-1,l-y)]));
if(k<n&&n-k>x-i)ans=max(ans,f[i][j][k+1][l]=max(f[i][j][k+1][l],f[i][j][k][l]+a[k+1][min(l,m-y+j)]-a[k+1][max(j-1,l-y)]));
if(j>1&&j-1>l-y)ans=max(ans,f[i][j-1][k][l]=max(f[i][j-1][k][l],f[i][j][k][l]+b[min(k,n-x+i)][j-1]-b[max(i-1,k-x)][j-1]));
if(l<m&&m-l>y-j)ans=max(ans,f[i][j][k][l+1]=max(f[i][j][k][l+1],f[i][j][k][l]+b[min(k,n-x+i)][l+1]-b[max(i-1,k-x)][l+1]));
}
}
printf("%d",ans);
}