UVA1103 古代象形符号 Ancient Messages 题解

时间:2024-09-09 22:37:38

题目链接:

https://www.luogu.org/problemnew/show/UVA1103

题目分析:

我们可以先进行矩阵的还原

for(int k=1;k<=4;k++)
{
a[i][++cnt]=(tmp>>(4-k))&1;
}

这种使用for语句的方法在其他题解内貌似没有提及,(但其实就是把anguei的化简了一下)

这样就能复原出原始的数据(01矩阵)

然后我们可以发现每一个象形文字都有可放缩性,但空白的个数是一定的。例如虫子图案就有4个空白处。

这样我们可以利用这一特性来解决问题了。

接下来用的算法是dfs乃至bfs入门都很常见的经典模型——水洼(或细胞个数)。

我们可以先判断与矩阵边缘联通的空白,全部消掉,然后剩下的空白就是文字中的了。

那么如何判断是哪个文字中的空白呢?

算法1:

刚开始,我是想先把每个文字复制一份到另一个数组里,那么在数组里经过边缘处理后剩下的空白联通块个数即为这个文字的个数。

但是后来发现没有必要。

算法2:

我们可以直接找黑点,找到一个开始扩张,扩张到的白点就是该文字的了。。。

还有就是千万不要犯一个错误:

输出的顺序是题目中图形出现的先后顺序而不是空白的个数为顺序。

endendend

代码:

//主要思路:先把二进制的01矩阵还原出来,记在a数组里,然后一一把每个象形文字单独放到b数组里,用从外向内缩0的办法找出在图形内的空白0,然后数出来,结束。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
using namespace std;
int a[205][205];
int aa[5]={0,1,-1,0,0};
int bb[5]={0,0,0,-1,1}; int ans;
int jl[7];
int H,W;
char st[6]={'W','A','K','J','S','D'};
void pd(int xx,int yy)
{
a[xx][yy]=2;
for(int i=1;i<=4;i++)
{
int x=xx+aa[i];
int y=yy+bb[i];
if(x>0&&y>0&&x<=H&&y<=W&&a[x][y]==0)
{
a[x][y]=2;
pd(x,y);
}
}
}
void search(int xx,int yy)
{
a[xx][yy]=2;
for(int i=1;i<=4;i++)
{
int x=xx+aa[i];
int y=yy+bb[i];
if(x>0&&y>0&&x<=H&&y<=W&&a[x][y]!=2)
{ if(a[x][y]==0)
{
ans++;
pd(x,y);
}
else
if(a[x][y]==1) search(x,y); }
}
} int main()
{
char s[55];
int cntt=0;
while(~scanf("%d%d",&H,&W)&&H!=0&&W!=0)
{
memset(jl,0,sizeof(jl));
memset(a,0,sizeof(a));
ans=0;
cntt++;
for(int i=1;i<=H;i++)
{
cin>>s;
int cnt=0;
for(int j=1;j<=W;j++)
{
int tmp;
sscanf(s+j-1,"%1x",&tmp);
//printf("%1x",tmp);
//printf("\n");
for(int k=1;k<=4;k++)
{
a[i][++cnt]=(tmp>>(4-k))&1;
}
}
}
W*=4; /*for(int i=1;i<=H;i++)
{
for(int j=1;j<=W;j++)
{
printf("%d",a[i][j]);
}
printf("\n");
}*/
for(int k=1;k<=H;k++)
{
if(a[k][1]==0)pd(k,1);
if(a[k][W]==0)pd(k,W);
}
for(int k=1;k<=W;k++)
{
if(a[1][k]==0)pd(1,k);
if(a[H][k]==0)pd(H,k);
}
/* for(int qwq=1;qwq<=H;qwq++)
{
for(int qaq=1;qaq<=W;qaq++)
{
printf("%d",a[qwq][qaq]);
}
printf("\n");
}*/
for(int i=1;i<=H;i++)
{
for(int j=1;j<=W;j++)
{
/*printf("--------\n");
for(int qwq=1;qwq<=H;qwq++)
{
for(int qaq=1;qaq<=W;qaq++)
{
printf("%d",a[qwq][qaq]);
}
printf("\n");
}*/
if(a[i][j]==1)
{
//print();
ans=0;
search(i,j);
//printf("ans=%d\n",ans);
jl[ans]++;
//printf("ans=%d\n",ans);
}
/* for(int i=1;i<=H;i++)
{
for(int j=1;j<=W;j++)
{
printf("%d",a[i][j]);
}
printf("\n");
}*/
}
}
printf("Case %d: ",cntt);
for(int j=1;j<=jl[1];j++)
{
printf("%c",st[1]);
}
for(int j=1;j<=jl[5];j++)
{
printf("%c",st[5]);
}
for(int j=1;j<=jl[3];j++)
{
printf("%c",st[3]);
}
for(int j=1;j<=jl[2];j++)
{
printf("%c",st[2]);
}
for(int j=1;j<=jl[4];j++)
{
printf("%c",st[4]);
}
for(int j=1;j<=jl[0];j++)
{
printf("%c",st[0]);
}
printf("\n");//qaqqwqwedffg }
return 0;return 0;
}

撒花~