uva 1103 详解

不要受上一题的影响(uva572),此处的连通没有对角线方向。

基本思路:

1.在还原的二进制图再增加一圈0(没必要处理,只需改变一下边界)。

2.将最外圈的0以及与最外圈的0相连通的0赋值为-1(可以是非0非1的任何数,此处只是做标记)。

3.按照1的连通块找里面的0(同时将找过的1标记为-1),找到0即是里面的一个”洞“,并将这个”洞“用-1标记。

4.将一个完整的1的连通块找完后,看有多少个”洞“,即为哪个图形。

5.循环步骤3、4,直到找完。

样例输入:

5 5
fffff
0f0f0
fffff
0f0f0
fffff

二进制图(加上外圈0)
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0


代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=200+10;
int pic[maxn][maxn];
int m,n;
int circle;
int sixteen[16][4]=						
{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},
 {0,1,0,0},{0,1,0,1},{0,1,1,0},{0,1,1,1},
 {1,0,0,0},{1,0,0,1},{1,0,1,0},{1,0,1,1},
 {1,1,0,0},{1,1,0,1},{1,1,1,0},{1,1,1,1}
};
void DFS0(int i,int j)				//此递归有两个用处:1.标记最外层0   2.填“洞”
{
	if(i>m+1||i<0||j>n+1||j<0||pic[i][j]!=0)	//外圈0
		return;
	pic[i][j]=-1;
	DFS0(i-1,j);
	DFS0(i+1,j);
	DFS0(i,j-1);
	DFS0(i,j+1);
}
void DFS1(int i,int j)				//按照1的连通块寻找“洞”
{
	if(i>m+1||i<0||j>n+1||j<0||pic[i][j]==-1)	//外圈0
		return;
	if(pic[i][j]==0)
	{
		::circle++;
		DFS0(i,j);
		return;
	}
	pic[i][j]=-1;
	DFS1(i-1,j);
	DFS1(i+1,j);
	DFS1(i,j-1);
	DFS1(i,j+1);
}
int main()
{
	char ch[maxn];
	int K=0;
	while(scanf("%d %d",&m,&n)==2&&m&&n)
	{
		int sum[6]={0,0,0,0,0,0};
		memset(pic,0,sizeof(pic));			//别忘初始化
		for(int i=1;i<=m;i++)				//从1开始空出外圈一行0
		{
			int h=1;
			scanf("%s",ch);
			for(int j=0;j<n;j++)
			{
				int num;
				if(ch[j]>='a'&&ch[j]<='z')
					num=ch[j]-87;
				else num=ch[j]-48;
				pic[i][h++]=sixteen[num][0];
				pic[i][h++]=sixteen[num][1];
				pic[i][h++]=sixteen[num][2];
				pic[i][h++]=sixteen[num][3];
			}
		}
		n=n*4;
//		for(int i=0;i<=m+1;i++)
//		{
//			for(int j=0;j<=n+1;j++)
//				cout<<pic[i][j]<<" ";
//			cout<<endl;
//		}
		DFS0(0,0);
		for(int i=1;i<=m;i++)			//只需判断还原的二进制图
			for(int j=1;j<=n;j++)
			if(pic[i][j]==1)
		{
			::circle=0;
			DFS1(i,j);
			sum[circle]++;
		}
		cout<<"Case "<<++K<<": ";
		if(sum[1]!=0)
			for(int i=0;i<sum[1];i++)
			cout<<'A';
		if(sum[5]!=0)
			for(int i=0;i<sum[5];i++)
			cout<<'D';
		if(sum[3]!=0)
			for(int i=0;i<sum[3];i++)
			cout<<'J';
		if(sum[2]!=0)
			for(int i=0;i<sum[2];i++)
			cout<<'K';
		if(sum[4]!=0)
			for(int i=0;i<sum[4];i++)
			cout<<'S';
		if(sum[0]!=0)
			for(int i=0;i<sum[0];i++)
			cout<<'W';
		cout<<endl;
	}
	return 0;
}



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值