搜索题以前做过几道,有一定的认识,首先这道题的难度是:读不懂题意。。。。
看了看网上的题意:好像明白了点,就是说有几块区域,*连通(是四连通,上下左右)的区域代表骰子,其中可能有
字符'X','X'可能叫做点数吧,字符'.'表示背景,不用管,就是让求一共有几块骰子以及他们分别表示的数是多
少,每个骰子区域中'X'的连通个数代表点数,比如题上一共有4个骰子,第一个是两点,第二个是1点,第三个是两
点,第四个是四点,输出按升序就ok了。
思路:
用双重搜索就可以,判断双重连通分量的个数,我用的是两个dfs,第一个是遍历'*'连通图,第二个是遍
历'X'的连通图,遍历'X'后都会把它改为字符'*',之后重新将它作为'*'遍历(刚开始就是在这wa的)忘了重新遍
历了,否则会多算的,因为'X'都是和'*'挨着的,所以每次进去的时候可以都从'*'进去。
代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char a[55][55];
int visit[55][55];
int dx[4]={-1,0,0,1};
int dy[4]={0,-1,1,0};
int s;
int res[100];
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
void dfs2(int x,int y)
{
void dfs1(int ,int );//声明dfs1函数,好久没声明过了
int i,j;
a[x][y] = '*';//如果当前字符为X,访问过后置为*
//visit[x][y] = 1;
for(i=0; i<4; i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if(a[xx][yy]=='X')
{
dfs2(xx,yy);//把所有的连通的'X'都访问一遍,置为'*'
}
}
return ;
}
void dfs1(int x,int y)
{
int i,j;
visit[x][y]=1;
for(i=0; i<4; i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if(!visit[xx][yy]&&(a[xx][yy]=='*'||a[xx][yy]=='X'))
{
if(a[xx][yy]=='X')
{
res[s]++; //每次出现X就说明了有一个连通分量,所以加一,之后必须处理它的连通分量,即调用dfs2
dfs2(xx,yy);
dfs1(xx,yy);//此处必须调用一下dfs1,因为前面是把它置为'*',所以要把它作为'*'再搜索一遍
//printf("########################\n");
}
else
dfs1(xx,yy);
}
}
return ;
}
int main()
{
int m,n,i,j;
int cnt = 0;
while(scanf("%d%d",&m,&n),(m!=0||n!=0))
{
cnt++;
s = 0;
int count1 = 0;
memset(visit,0,sizeof(visit));
memset(res,0,sizeof(res));
for(i=0; i<n; i++)
scanf("%s",a[i]);
// puts("");
/// puts("");
//
for(i=0; i<n; i++)
{
for(j=0; j<m; j++)
{
if(!visit[i][j]&&(a[i][j]=='*'))
{
//printf("x = %d y = %d\n",i,j);
count1++;//统计出现了多少*连通量
dfs1(i,j);
s++;
}
}
}
//for(i=0; i<s; i++)
//printf("%d ",res[i]);
// puts("");
qsort(res, s, sizeof(res[0]), cmp);
printf("Throw %d\n",cnt);
for(i=0; i<count1; i++)
{
printf("%d",res[i]);
if(i!=count1-1)
printf(" ");
}
puts("");
puts("");
}
}
504

被折叠的 条评论
为什么被折叠?



