搜索题以前做过几道,有一定的认识,首先这道题的难度是:读不懂题意。。。。
看了看网上的题意:好像明白了点,就是说有几块区域,*连通(是四连通,上下左右)的区域代表骰子,其中可能有
字符'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(""); } }