图论水题
与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;
}