紫书刷题进行中,题解系列点这里
习题3-6 UVA232 Crossword Answers(49行AC代码)
思路分析
给定N*M的网格,有黑白两种格子,从上到下,从左到右依次对左侧和上侧没有白格子的白格子进行标号,具体如下:
- 第一行和第一列的白格子均编号
- 其余行列,若一个白格子的左侧或上侧存在黑格子,则对其进行编号
编号完成后,分别按行和按列输出相应子串,子串以有编号的白格子开始,遇见黑格子或行列则结束。
因此,可用string数组
存放网格,一遍扫描后计算出存在编号的白格子
- 按行遍历输出即可完成按行输出子串
- 按列遍历则需将子串先存放与哈希数组,最后再按顺序输出
注意点
- 输出标号格式:右对齐,宽度为3,即
printf("%3d",..)
- 两个相邻puzzle间需多输出一个空行,最后一个puzzle不需要
- 当puzzle的行或列为空时,一样得输出
Across Down
AC代码(C++11,字符串处理,坑人输出)
#include<bits/stdc++.h>
using namespace std;
#define MAXN 11
string puzzle[MAXN];
int n, m, cnt = 0, num = 0, now, id[MAXN][MAXN] = {0}; // 编号
int main() {
while(scanf("%d", &n) == 1 && n != 0) {
scanf("%d", &m);
if (num != 0) printf("\n"); // 仅两个puzzle间需空行
printf("puzzle #%d:\n", ++num); // puzzle标号
cnt = 0; // 统计每个有编号的格子
printf("Across\n"); // 横向输出
for (int i = 0; i < n; i ++) {
cin >>puzzle[i];
for (int j = 0; j < m; j ++) { // 标记有编号的格子
if ((i == 0 || j == 0) && puzzle[i][j] != '*') id[i][j] = ++cnt; // 第一行/列全部编号
else { // 当前白格子上方或左方存在黑格子
if (puzzle[i][j] != '*'
&& (puzzle[i][j-1] == '*' || puzzle[i-1][j] == '*')) id[i][j] = ++cnt;
}
}
for (int j = 0; j < m; ) { // 横向输出
if (puzzle[i][j] == '*') j++;
else {
printf("%3d.", id[i][j]); // 宽度3,右对齐!!!
while(j < m && puzzle[i][j] != '*') printf("%c", puzzle[i][j++]);
printf("\n");
}
}
}
printf("Down\n"); // 纵向输出
string ans[101]; // 保存每个标号对应结果
for (int j = 0; j < m; j ++) { // 存放与ans中
for (int i = 0; i < n; ) {
if (puzzle[i][j] == '*') i ++;
else {
now = id[i][j];
while(i < n && puzzle[i][j] != '*') ans[now] += puzzle[i++][j];// printf("%c", puzzle[i++][j]);
}
}
}
for (int i = 1; i < 101; i ++) { // 将ans中记录的值顺序输出
if (!ans[i].empty()) {
printf("%3d.%s\n", i, ans[i].c_str()); // 宽度3,右对齐!!!
}
}
}
return 0;
}
来源:CSDN
作者:是阿俊呐
链接:https://blog.csdn.net/qq_40738840/article/details/104174763