该题与poj1888相似,连接为:http://poj.org/problem?id=1888
题意如下:
交叉字谜是一个很有趣的游戏。将地图分成一个个后挖空一些格子,剩下的格子中,连续的格子填入单词,由此填满整个地图。对于水平方向上连续的格子,自左至右填入一个单词,每个格子一个字母;竖直方向上的连续格子则是自上至下填入单词。现给每个单词分别编号,编号的规则如下。自左向右遍历一行,自上而下遍历所有行。对于每一个格子,若该格子为“水平序列”的首字母,或者是“竖直序列”的首字母,则给予编号,作为该单词的编号。若同时为两种序列的首字母,编号用同一个。其中,序列的定义为,序列方向上的前一个位置为空格子或地图外,后一个位置为空格子或地图外。现给定一个字谜游戏的答案,问按上述规则给每个格子进行编号后,两个方向上各个编号的单词分别是什么。
思路:模拟题。直接按编号规则扫描地图编号即可。扫描至某个字母时,若该字母为标记,则说明该字母为序列首部。此时,按特定方向扫描,直至遇到空格子或地图外位置,沿途的字母全部标记,说明这些字母都不是序列首。需要注意的是,“水平序列”与“竖直序列”是相对独立的。也就是说,一个字母即使是水平序列的中间元素,也有可能是竖直序列的首部。所以这里的标记数组我用了两个,分别记录两个方向上遍历情况。最后就是要注意一下输出格式
该题的代码为:
#include "stdio.h"
#include "string.h"
#define M 15
char s[M][M];
int r,c;
int pl[M][M],ph[M][M],mm[M][M];
int main()
{
int i,j,k,t;
int tc=1,ans;
while(scanf("%d",&r)>0)
{
if(r==0) break;
scanf("%d",&c);
for(i=0;i<r;i++)
scanf("%s",s[i]);
printf("puzzle #%d:\n",tc++);
memset(pl,0,sizeof(pl));
memset(ph,0,sizeof(ph));
memset(mm,0,sizeof(mm));
ans=1;
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
if(s[i][j]!='*')
{
if(pl[i][j]==0)
{
mm[i][j]=ans;ans++;
k=j+1;
while(s[i][k]!='*'&&k<c)
{
pl[i][k]=1;
k++;
}
}
if(ph[i][j]==0)
{
if(mm[i][j]==0)
{
mm[i][j]=ans;
ans++;
}
k=i+1;
while(s[k][j]!='*'&&k<r)
{
ph[k][j]=1;
k++;
}
}
}
}
}
/*for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
printf("%d ",mm[i][j]);
}
printf("\n");
}*/
printf("Across\n");
for(i=0;i<r;i++)
for(j=0;j<c;j++)
{
if(mm[i][j]&&!pl[i][j])
{
printf("%3d.%c",mm[i][j],s[i][j]);
k=j+1;
while(pl[i][k])
{
printf("%c",s[i][k]);
k++;
}
printf("\n");
}
}
printf("Down\n");
for(i=0;i<r;i++)
for(j=0;j<c;j++)
{
if(mm[i][j]&&!ph[i][j])
{
printf("%3d.%c",mm[i][j],s[i][j]);
k=i+1;
while(ph[k][j])
{
printf("%c",s[k][j]);
k++;
}
printf("\n");
}
}
printf("\n");
}
return 0;
}