2012杭州赛区网络赛 - 1005 - Finding crosses - HDU - 4414

/*暴力DFS+BFS,先DFS求出中心点,中心点的条件是它周围有四个点
然后BFS判断是否为十字架,判断条件:'#'数量=4*层数+1
自制测试样例:
5
o#oo#
####o
o#o#o
oo###
ooo#o
5
o#oo#
###oo
o#o#o
oo###
ooo#o
5
oo#oo
oo#oo
#####
oo#oo
oo#oo
3
o#o
###
o#o

0
2
1
1
*/
#include<stdio.h>
#include<string.h>
char grid[70][70];
int vis[70][70],midx[70],midy[70],top;
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
int N,acquire;
typedef struct node
{
    int x,y;
}Node;
Node queue[30000];    
int BFS(int x,int y)
{
    int rear,front;
    int nx,ny,ox,oy;
    int i,j,k,cnt,step=4;/*step为层数*/
    cnt=rear=front=0;
    queue[rear].x=x;
    queue[rear++].y=y;
    vis[x][y]=1;
    while(front<rear)
    {
        cnt=0;
        ox=queue[front].x;oy=queue[front++].y;
        for(i=0;i<4;i++)
        {
            nx=ox+dx[i];ny=oy+dy[i];
            if(nx>=0&&nx<N&&ny>=0&&ny<N&&grid[nx][ny]=='#'&&!vis[nx][ny])
            {
                cnt++;
                queue[rear].x=nx;queue[rear++].y=ny;
                vis[nx][ny]=1;
            }
        } 
        if(cnt==1)step++;
    }
    step/=4;
    if(rear==step*4+1)acquire++;
    return 0;     
}   
int DFS(int x,int y)
{
    int nx,ny;
    int i,j,k,cnt=0;
    for(i=0;i<4;i++)
    {
        nx=x+dx[i];ny=y+dy[i];
        if(nx>=0&&nx<N&&ny>=0&&ny<N&&!vis[nx][ny]&&grid[nx][ny]=='#')
        {
            cnt++;
            vis[nx][ny]=1;
            DFS(nx,ny);
        }    
    }
    if(cnt==3)
    {
        midx[top]=x;
        midy[top++]=y;
    }
    return 0;      
}     
int main()
{
    int i,j,k;
    while(scanf("%d",&N)!=EOF&&N)
    {
        memset(vis,0,sizeof(vis));
        acquire=top=0;
        for(i=0;i<N;i++)scanf("%s",grid[i]);
        for(i=0;i<N;i++)
        {
            for(j=0;j<N;j++)
            {
                if(!vis[i][j]&&grid[i][j]=='#')
                {
                    vis[i][j]=1;
                    DFS(i,j);
                }    
            }
        }  
        memset(vis,0,sizeof(vis));
        for(i=0;i<top;i++)
        {
            if(!vis[midx[i]][midy[i]])BFS(midx[i],midy[i]);
        }        
        printf("%d\n",acquire);
    }
    return 0;
}        
    

/*非常感谢 BJTUlxc 同学的提问,我发现了老程序的漏洞,现在新的代码修补了那个BUG
比赛的测试数据给得比较水,让我侥幸通过了。。。下面是新代码:
改进:记录父点的方向,统计一条直线上点的个数,判断是否有邻接点。 
暴力DFS+BFS,先DFS求出中心点,中心点的条件是它周围有四个点
然后BFS判断是否为十字架,判断条件:四个方向的'#'数目相同并且没有多余邻接点(发生转弯) 
自制测试样例:
5
o#oo#
####o
o#o#o
oo###
ooo#o
5
o#oo#
###oo
o#o#o
oo###
ooo#o
5
oo#oo
oo#oo
#####
oo#oo
oo#oo
3
o#o
###
o#o

0
2
1
1
*/
#include<stdio.h>
#include<string.h>
char grid[70][70];
int vis[70][70],midx[70],midy[70],top;
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
int N,acquire;
int tagd[4];/*记录四个方向上的'#'个数*/
typedef struct node
{
    int x,y;
    int di;
}Node;
Node queue[30000];    
int BFS(int x,int y)
{
    int rear,front;
    int nx,ny,ox,oy,direct;/*direct 记录父点的方向*/
    int i,j,k,flag;/*flag记录是否发生转弯现象*/
    flag=rear=front=0;
    queue[rear].x=x;
    queue[rear++].y=y;
    vis[x][y]=1;
    while(front<rear)
    {
        ox=queue[front].x;oy=queue[front].y;direct=queue[front++].di;
        if(front==1)
        {
            for(i=0;i<4;i++)
            {
                nx=ox+dx[i];ny=oy+dy[i];
                if(nx>=0&&nx<N&&ny>=0&&ny<N&&grid[nx][ny]=='#'&&!vis[nx][ny])
                {
                    tagd[i]++;
                    queue[rear].x=nx;queue[rear].y=ny;queue[rear++].di=i;
                    vis[nx][ny]=1;
                }
            } 
        }
        else
        {
            for(i=0;i<4;i++)
            {
                nx=ox+dx[i];ny=oy+dy[i];
                if(nx>=0&&nx<N&&ny>=0&&ny<N&&grid[nx][ny]=='#'&&!vis[nx][ny])
                {
                    if(i!=direct)flag=1;/*子点方向与父点方向不一致*/
                    tagd[i]++;
                    queue[rear].x=nx;queue[rear].y=ny;queue[rear++].di=i;
                    vis[nx][ny]=1;
                }
            }
        }    
    }
    if(!flag&&tagd[0]==tagd[1]&&tagd[1]==tagd[2]&&tagd[2]==tagd[3])acquire++;/*四个方向子点个数相同并且无转弯现象(邻接点)*/
    return 0;     
}   
int DFS(int x,int y)
{
    int nx,ny;
    int i,j,k,cnt=0;
    for(i=0;i<4;i++)
    {
        nx=x+dx[i];ny=y+dy[i];
        if(nx>=0&&nx<N&&ny>=0&&ny<N&&!vis[nx][ny]&&grid[nx][ny]=='#')
        {
            cnt++;
            vis[nx][ny]=1;
            DFS(nx,ny);
        }    
    }
    if(cnt==3)
    {
        midx[top]=x;
        midy[top++]=y;
    }
    return 0;      
}     
int main()
{
    int i,j,k;
    while(scanf("%d",&N)!=EOF&&N)
    {
        memset(vis,0,sizeof(vis));
        acquire=top=0;
        for(i=0;i<N;i++)scanf("%s",grid[i]);
        for(i=0;i<N;i++)
        {
            for(j=0;j<N;j++)
            {
                if(!vis[i][j]&&grid[i][j]=='#')
                {
                    vis[i][j]=1;
                    DFS(i,j);
                }    
            }
        }  
        memset(vis,0,sizeof(vis));
        for(i=0;i<top;i++)
        {
            if(!vis[midx[i]][midy[i]])
            {    
                memset(tagd,0,sizeof(tagd));
                BFS(midx[i],midy[i]);  
            }    
        }        
        printf("%d\n",acquire);
    }
    return 0;
}        
    


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值