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("
");   
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/12483804.html