Uva 657

图论水题

与UVa 572略微类似。

总体思路:先找出每个色子来,然后每一片色子做上自己的标记,深搜一遍。找出‘*’标记的联通分支的个数

    扫完一遍以后再扫一遍,此次利用不同色子的独特标记来区分色子,找出‘X’联通分支的个数。最后排序输出。

开始看成8连通域了。。。。。wa。。。

后来每行的最后多输出了一个空格,然后一直PE。。。。。。T_T囧啊。。。。囧啊。。。。

代码如下:

/*
Uva 657
2012-10-15 19:52:01
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>


char maps[51][51];
int dice_count=0;
int visited_in_pic[51][51];//色子有没有被访问过以及色子的编号
int visited_in_dice[51][51];//每个色子中间的访问记号
int w,h;
int count[100]={0};//每个色子中的'X'联通分支的个数
int cmp(const void * a, const void * b) //快排用的比较函数
{
    return *(int *) a - *(int *) b;
}


void ini()//初始化
{
    for(int i=0;i<100;++i)
    {
        count[i]=0;
    }
    for(int i=0;i<51;++i)
    {
        for(int j=0;j<51;++j)
        {
            visited_in_dice[i][j]=0;
            visited_in_pic[i][j]=0;
        }
    }
}
void DFS(int x,int y,int code)//深搜,搜色子,并作标记
{
    if(x>=h||y>=w||x<0||y<0||visited_in_pic[x][y]!=0||maps[x][y]=='.')
        return ;
    visited_in_pic[x][y]=code;//code指使色子的编号
    DFS(x,y-1,code);
    DFS(x-1,y,code);
    DFS(x+1,y,code);
    DFS(x,y+1,code);
}
void DFS2(int x,int y)//色子完事以后在一个色子“内部”搜索,写两个深搜就是为了省事。。。其实一个就够了。。不愿意改了。。。
{
    if(x>=h||y>=w||x<0||y<0||visited_in_dice[x][y]==1||maps[x][y]=='.'||maps[x][y]=='*')
        return ;
    visited_in_dice[x][y]=1;
    DFS2(x,y-1);
    DFS2(x-1,y);
    DFS2(x+1,y);
    DFS2(x,y+1);
}
int main()
{
    int ccc=1;
    int mark=0;
    while(scanf("%d%d",&w,&h)!=EOF)
    {
        ini();
        getchar();
        dice_count=0;
        if(w==0&&h==0)
            return 0;
        for(int i=0;i<h;++i)
        {
            gets(maps[i]);
        }
         printf("Throw %d\n",ccc++);
        for(int i=0;i<h;++i)
        {
            for(int j=0;j<w;++j)
            {
                if(visited_in_pic[i][j]==0&&maps[i][j]!='.')//如果碰到新的联通分量,那么计数器加1并且标记色子编号
                {
                    dice_count++;
                    DFS(i,j,dice_count);//标号
                }
            }
        }
        for(int i=0;i<h;++i)
        {
            for(int j=0;j<w;++j)
            {
                if(visited_in_dice[i][j]==0&&maps[i][j]!='.'&&maps[i][j]!='*')
                {
                    (count[visited_in_pic[i][j]-1])++;//按照编号来统计'X'联通分支的个数
                    DFS2(i,j);
                }
            }
        }
        qsort(count,dice_count,sizeof(int),cmp);//排个序
        for(int i=0;i<dice_count;++i)
        {
            printf("%d",count[i]);
            if(i!=dice_count-1)//一定注意啊。。。。PE都快吐了。。。。
            printf(" ");
        }
        printf("\n");
        mark=1;//也是PE。。不过这个好点
        if(mark)
            printf("\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值