LOJ #2733. 「JOISC 2016 Day 2」三明治 DFS
这个可以爆搜,如果搜出来环的话就一定不合法.
这个时间复杂度是 $O(n^4)$ 的.
但是我们发现,如果向右侧搜的话右侧许多方块会把很多状态都提前搜出来了.
所以我们可以从左向右枚举,搜左面.从右向左枚举,搜右面.
这样时间复杂度就是 $O(n^3)$ 的了.
code:
#include <bits/stdc++.h> #define N 405 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n,m,vis[N][N],tot,ans[N][N]; int dx[]={0,-1,0,1}; int dy[]={-1,0,1,0}; char str[N][N]; void dfs(int x,int y,int d) { if(x<1||x>n||y<1||y>m) return; if(vis[x][y]) { if(vis[x][y]==-1) tot=1<<30; return; } tot+=2; vis[x][y]=-1; dfs(x+dx[d],y+dy[d],d); d^=str[x][y]=='N'?3:1; dfs(x+dx[d],y+dy[d],d); vis[x][y]=1; } int main() { // setIO("input"); int i,j; scanf("%d%d",&n,&m); for(i=1;i<=n;++i) { scanf("%s",str[i]+1); for(j=1;j<=m;++j) ans[i][j]=1<<30; } for(i=1;i<=n;++i) { memset(vis,0,sizeof(vis)); tot=0; for(j=1;j<=m;++j) { dfs(i,j,0); ans[i][j]=min(ans[i][j],tot); } memset(vis,0,sizeof(vis)); tot=0; for(j=m;j;--j) { dfs(i,j,2); ans[i][j]=min(ans[i][j],tot); } for(j=1;j<=m;++j) printf("%d ",ans[i][j]==1<<30?-1:ans[i][j]); printf("\n"); } return 0; }