题意:
给一个 r 行 l 列的棋盘,每个格子中有字母或 ‘*’。
并告知存在特殊的格子,即最左边一列的字母格子、最上边一列的字母格子、左边或上边有 ‘*’ 格子的字母格子。
按照从左往右,从上往下的顺序对这些特殊格子进行编号就得到了题目给的图中的编号,即下图:
题目要求打印两组数据,一组是 Across,一组是 Down。
对于 Across 组,就是按照编号的顺序一行一行地找字符串,该字符串以编了号的字母为开始,向右延伸,直到遇到 ‘*’ 格子或行末。输出过的字母就不能再作为字符串开头了。
比如输出了 1、2、3 格子的字母,是以 1 号格子为开头的,2、3 号格子的字母已经输出过了,接下去就不用再以 2 号格子为开头或 3 号格子为开头找字符串了。
对于 Down 组,就是按照编号的顺序一列一列地找字符串,该字符串以编了号的字母为开始,向下延伸,直到遇到 ‘*’ 格子或行末。同 Across 组,输出过的字母就不能再作为字符串开头了。
此处,Down 组的按照编号的顺序这一要求需要强调一下,要使输出的编号从上往下是从小到大的。
思路:
1. 读取数据
2. 处理出编号
3. 输出 Across 组的数据,注意给输出过的字母打上标记
4. 输出 Down 组的数据,注意给输出过的字母打上标记
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
#include<queue>
#include<utility>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#include<sstream>
using namespace std;
typedef long long LL;
int r, l;
char ch[105][105];
int num[105][105];
bool flag[105][105];
int main()
{
//freopen("in.txt", "r", stdin);
int kase = 1;
while(scanf("%d", &r)==1 && r!=0){
scanf("%d", &l);
if(kase != 1) printf("\n");
printf("puzzle #%d:\n", kase++);
for(int i=0; i<r; i++){
scanf("%s", ch[i]);
}
//产生编号
memset(num, 0, sizeof(num));
int n = 1;
for(int i=0; i<r; i++){
for(int j=0; j<l; j++){
if((i==0 || j==0) && ch[i][j]!='*'){
num[i][j] = n++;
}else if((i>0&&ch[i-1][j]=='*' || j>0&&ch[i][j-1]=='*') && ch[i][j]!='*'){
num[i][j] = n++;
}
}
}
//输出 Across 组数据
memset(flag, false, sizeof(flag));
printf("Across\n");
for(int i=0; i<r; i++){
for(int j=0; j<l; j++){
if(num[i][j]!=0 && !flag[i][j]){
printf("%3d.", num[i][j]);
int y = j;
while(y<l && ch[i][y]!='*') {
if(!flag[i][y]) flag[i][y] = true;
putchar(ch[i][y]);
y++;
}
printf("\n");
}
}
}
//输出 Down 组数据
memset(flag, false, sizeof(flag));
printf("Down\n");
for(int i=0; i<r; i++){
for(int j=0; j<l; j++){
if(num[i][j]!=0 && !flag[i][j]){
printf("%3d.", num[i][j]);
int x = i;
while(x<r && ch[x][j]!='*') {
if(!flag[x][j]) flag[x][j] = true;
putchar(ch[x][j]);
x++;
}
printf("\n");
}
}
}
}
return 0;
}
想看书上的源代码的话看这 (^▽^)
https://github.com/aoapc-book/aoapc-bac2nd