习题3-6 纵横字谜的答案(Crossword Answers, ACM/ICPC World Finals 1994,UVa232)
题目
输入一个r 行c 列(1<r,.c<10) 的网格,黑格用“”每个白格都填有一个字母。如果一个白格的左边相邻位置或者上边相邻位置没有白格(可能是黑格,也可能出了网格边界),则称这个白格是一个起始格
你的任务是找出网格中所有所有横向单词(Across)。.这些单词必须从一个起始格(左边是黑格,或是第一列) 开始,向右延伸到一个黑格的左边或者整个网格的最右列。然后找出所有竖向单词(Down)。
这些单词必须从一个起始格(上边是黑格,或是第一行) 开始,向下延伸到一个黑格的上边或者整个网格的最下行。
输入:
有多个矩阵输入,每一个矩阵都是以RC 开始(1<r,c<10),表示R 行C 列,然后下面紧跟着一个R 行C 列的矩阵,里面全部是大写字母或是,以,C 代表所有矩阵输入结束。
输入输出格式(洛谷)
还是老样子空行分隔,最后一行不需要空行
输出单词的序号需要右对齐(“%3d”)
//输入格式
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
代码
#include <stdio.h>
#include <string.h>
char a[15][15];
char b[15][15];
int main(){
int r,c;
int g=1;
while(1){
if(scanf("%d",&r)==1 && r==0){
break;
}
scanf("%d",&c);
int k=1;
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
while(scanf("%c",&a[i][j]) && (a[i][j]=='\n' || a[i][j]==' ') );
if(a[i][j]!='*' && (i-1<0 ||j-1<0 ||a[i-1][j]=='*' ||a[i][j-1]=='*')){
b[i][j]=k++;
}
}
}
if(g>1){
printf("\n");
}
printf("puzzle #%d:\n",g++);
printf("Across\n");
for(int i=0;i<r;i++){
int flag=0;
for(int j=0;j<c;j++){
if(a[i][j]!='*'){
if(flag==0){
printf("%3d.",b[i][j]);
flag=1;
}
if(j+1>=c || a[i][j+1]=='*'){
printf("%c\n",a[i][j]);
flag=0;
}else{
printf("%c",a[i][j]);
}
}
continue;
}
}
printf("Down\n");//本想横向改一下直接用,
//不乘想纵向输出也要按序号升序来,只好重写
int f=r*c;
int g=0;
while(g<f){
int j=g%c;
int i=g/c;
if(*(*(a+i)+j)!='*' &&(g<c || *(*(a+i-1)+j)=='*')){
int flag=0;
for(;i<r;i++){
if(flag==0){
printf("%3d.",b[i][j]);
flag=1;
}
if(i+1>=r || a[i+1][j]=='*'){
printf("%c\n",a[i][j]);
break;
}else{
printf("%c",a[i][j]);
}
}
}
g++;
}
}
return 0;
}
总结
3个小时一道题,这速度真的没救了