当前位置: 代码迷 >> 综合 >> UVa 232 Crossword Answers (纵横字谜的答案)
  详细解决方案

UVa 232 Crossword Answers (纵横字谜的答案)

热度:10   发布时间:2023-12-08 11:27:50.0


题意:

白格:该位置字符是字母;黑格:该位置字符是'*';

起始格:一个白格的左边相邻位置或者上边相邻为之没有白格(可能是黑格或超出网格边界);

把起始格按照从上到下、从左到右顺序编号(1,2,3,4...)

横向单词(Across):从起始格开始且前一个不是白格,一直向右直到遇到黑格或除了边界。

竖向单词(Down):从起始格开始且上一个不是白格,一直向下直到遇到黑格或除了边界。

输入:

多组测试数据。每组数据第一行两个r,c数字,分别是网格行数和列数。

接下来是r行字符每行c列

遇到开始输入数字0结束输入。

输出:

相邻两个测试组之间有空行,但末尾无空行。

测试组找不出横向单词或竖向单词时,仍需输出Across或Down。

对于每个单词输出首字母的起始格编号。

其他细节参照样例。


先贴出AC代码,再讲下调试中遇到的问题。

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{//freopen("in.txt", "r", stdin);//freopen("out.txt", "w", stdout);char s[11][11];int r, c, i, j, k, a[11][11], d[11][11], first=1, count=0;while (~scanf("%d",&r)&&r){scanf("%d", &c);for (i = 1;i <= r;i++)scanf("%s", s[i]+1);//···①memset(a, 0, sizeof(a));memset(d, 0, sizeof(d));k = 0;for (i = 1;i <= r;i++)for (j = 1;j <= c;j++){if (s[i][j]!='*') a[i][j] = 1;//a[i][j]=1表示白格if (a[i][j]&&(a[i][j-1]==0||a[i-1][j]==0)) d[i][j] = ++k;//d[i][j]=k表示该起始格的编号是k}/* ···②for (i = 1;i <= r;i++)puts(s[i]+1);for (i = 1;i <= r;i++) {for (j = 1;j <= c;j++)printf("%d", a[i][j]);printf("\n");}for (i = 1;i <= r;i++) {for (j = 1;j <= c;j++)printf("%d", d[i][j]);printf("\n");}*/if (first) first = 0;else putchar('\n');printf("puzzle #%d:\nAcross\n", ++count);for (i = 1;i <= r;i++)for (j = 1;j <= c;j++){if (d[i][j] && a[i][j-1] ==0)//···③{printf("%3d.", d[i][j]);//···④for (k = j;a[i][k] == 1 && k <= c;k++)putchar(s[i][k]);putchar('\n');}}printf("Down\n");for (i = 1;i <= r;i++)for (j = 1;j <= c;j++){if (d[i][j]&&a[i-1][j]==0){printf("%3d.", d[i][j]);for (k = i;a[k][j] == 1 && k <= r;k++)putchar(s[k][j]);putchar('\n');}}}return 0;
}

首先遇到的问题在输入上,我是想使s[i][j]直接表示第i行第j列的字符,但是输入时没有对j考虑,也就是注释①的位置一开始写的是:
scanf("%s", s[i]);
然后通过添加注释②位置的代码,观察中间输出才改了过来。

注释③位置一开始并没有

&& a[i][j-1] ==0
没有对横向单词和竖向单词理解完全。

注释④处的%3d输出也是细节,需要对照样例观察,发现是三个单位右对齐的。