题目描述
做法
对于每个格子(i,j)设L(i,j)表示先吃靠左边界的格子至少要吃多少格子,R意义类似。
然后你发现L(i,j)>=L(i,j-1)。
于是一行一行做,每行才清空一次标记数组。
#include <cstdio>
#include <algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=400+10,inf=1000000005;
const int fx[4][2]={{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
const int trans[2][4]={{3, 2, 1, 0}, {2, 3, 0, 1}};
char s[maxn][maxn];
int L[maxn][maxn],R[maxn][maxn],bz[maxn][maxn];
int i,j,k,l,t,n,m,ans;
char get(){
char ch=getchar();
while (ch!='Z'&&ch!='N') ch=getchar();
return ch;
}
int dfs(int x,int y,int f){
if (bz[x][y]==1) return inf;
if (bz[x][y]==2) return 0;
bz[x][y]=1;
int i,d[2];
d[0]=f;d[1]=trans[s[x][y]=='Z'][f];
int ans=2,xx,yy;
fo(i,0,1){
xx=x+fx[d[i]][0];yy=y+fx[d[i]][1];
if (1<=xx&&xx<=n&&1<=yy&&yy<=m) ans+=dfs(xx,yy,d[i]);
}
bz[x][y]=2;
return min(ans,inf);
}
int main() {
freopen("sandwich.in","r",stdin);freopen("sandwich.out","w",stdout);
scanf("%d%d", &n, &m);
fo(i,1,n)
fo(j,1,m)
s[i][j]=get();
fo(i,1,n){
fo(j,1,n)
fo(k,1,m)
bz[j][k]=0;
fo(j,1,m) L[i][j]=min(L[i][j-1]+dfs(i,j,2),inf);
}
fo(i,1,n){
fo(j,1,n)
fo(k,1,m)
bz[j][k]=0;
fd(j,m,1) R[i][j]=min(R[i][j+1]+dfs(i,j,3),inf);
}
fo(i,1,n){
fo(j,1,m){
ans=min(L[i][j],R[i][j]);
if (ans!=inf) printf("%d ",ans); else printf("-1 ");
}
printf("\n");
}
}