《算法竞赛入门经典(第2版)》 习题3-6 纵横字谜的答案(Crossword Answers, ACM/ICPC World Finals 1994, UVa232)
输入一个r行c列(1<=r,c<=10)的网格,黑格用“*”表示,每个白格都填有一个字母。如果一个白格的左边相邻位置或者上边相邻位置没有白格(可能是黑格,也可能出了网格边界),则称这个白格是一个起始格。首先把所有起始格按照从上到下、从左到右的顺序编号为1,2,3,…,如图3-7所示。接下来要找出所有横向单词(Across)。这些单词必须从一个起始格开始,向右延伸到一个黑格的左边或者整个网格的最右列。最后找出所有竖向单词(Down)。这些单词必须从一个起始格开始,向下延伸到一个黑格的上边或者整个网格的最下行。
输入
每一个字谜网格的输入数据第1行是两个整数r和c,(1 ≤ r ≤ 10 且 1 ≤ c ≤ 10),r是网格的行数,c是网格的列数。接下来是r行字符,每行的字符都有c个,这些字符描述了网格的构成。这些字符或者是字母,或者是用来表示黑格的’*‘号。全部输入的最后是单独的一行,仅包含一个数字’0’。【注意:输入的不同网格之间没有其它内容分隔】
示例输入
2 2 AT *O 6 7 AIM*DEN *ME*ONE UPON*TO SO*ERIN *SA*OR* IES*DEA 0
示例输出
puzzle #1: Across 1.AT 3.O Down 1.A 2.TO puzzle #2: Across 1.AIM 4.DEN 7.ME 8.ONE 9.UPON 11.TO 12.SO 13.ERIN 15.SA 17.OR 18.IES 19.DEA Down 1.A 2.IMPOSE 3.MEO 4.DO 5.ENTIRE 6.NEON 9.US 10.NE 14.ROD 16.AS 18.I 20.A
分析
这又是一个模拟题,只要照着题目描述的做即可。值得注意的是,每次准备读入一个网格的数据时,一定要将网格数组清零、起始格数据清零、起始格数量清零,但是不要将网格数量清零。==清零,重要。==然后,就可以愉快的开始读入一个网格的数据了。稳妥起见,可以先读一个r,如果它是0,则结束程序,如果不是0,继续读入c。 接下来,就要逐个记录起始格。可以将第i个起始格的x、y坐标保存在x[i]、y[i]这两个数组中。如果你之前建立网格数组的时候建得比较大,且全部置0了,然后从下标1开始存储——那么现在判断起始格就无需担心数组越界问题,只要一个白格的左边或上边不是白格,就可以记录起始格了。 最后,就要分别输出横向与竖向单词了。输出完毕,不要忘记读取下一个r哟!
代码
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
char a
[12][12];
int x
[120];
int y
[120];
int r
, c
, tot
=0, heads
;
int main()
{
scanf("%d", &r
);
while(r
!=0)
{
memset(a
,0,12*12);
memset(x
,0,120);
memset(y
,0,120);
heads
= 0;
scanf("%d", &c
);
tot
++;
printf("\npuzzle #%d\n", tot
);
char in
;
int count
= 0, i
=1, j
=1;
while(count
<r
*c
)
{
in
= getchar();
if((in
>='A' && in
<='Z') || in
=='*'){
a
[i
][j
] = in
;
count
++;
j
++;
if(j
>c
) j
=j
%c
;
}
else if(in
=='\n' && count
>0) i
++;
}
for(i
=1; i
<=r
; i
++){
for(j
=1; j
<=c
; j
++)
if(a
[i
][j
]!='*' && (a
[i
-1][j
]==0 || a
[i
-1][j
]=='*' || a
[i
][j
-1]==0 || a
[i
][j
-1]=='*'))
{
heads
++;
x
[heads
] = i
;
y
[heads
] = j
;
}
}
printf("Across\n");
for(i
=1;i
<=heads
;i
++)
{
if(a
[x
[i
]][y
[i
]-1]==0 || a
[x
[i
]][y
[i
]-1]=='*'){
j
= y
[i
];
printf("=.", i
);
while(a
[x
[i
]][j
]!='*' && a
[x
[i
]][j
]!=0)
printf("%c", a
[x
[i
]][j
++]);
printf("\n");
}
}
printf("Down\n");
for(i
=1;i
<=heads
;i
++)
{
if(a
[x
[i
]-1][y
[i
]]==0 || a
[x
[i
]-1][y
[i
]]=='*'){
j
= x
[i
];
printf("=.", i
);
while(a
[j
][y
[i
]]!='*' && a
[j
][y
[i
]]!=0)
printf("%c", a
[j
++][y
[i
]]);
printf("\n");
}
}
scanf("%d", &r
);
}
return 0;
}