纵横字谜的答案(Crossword Answer ,ACM/ICPC World Finals 1994,UVa232)
题目描述:
题目来源于英文的猜字游戏。输入一个r行c列的网格,黑格用*号表示,每个白格都填有一个字母。
如果一个白格的左边相邻位置或者上边相邻位置没有白格(可能是黑格,也可能出了网格边界),则称这个白格是一个起始格。
首先把所有起始格从左到右,从上到下顺序编号1,2,3,。。。。
要求找出所有横向单词。这些单词必须从一个起始格开始,向右延伸到一个黑格的左边或者整个网格的最右边。
最后找出所有的竖向单词。
思路详解:
看代码。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int a,b;//记录行列
int k=1;//k是输入数据的编号,puzzle#k
while(cin>>a&&a!=0)
{
cin>>b;
getchar();
int num=0;
char s[15][15];//记录n*m的字符
int n[15][15];//记录n*m中白格子()的编号
for(int i=0;i<a;i++){
for(int j=0;j<b;j++){
//每输入一个字符就判断一次
cin>>s[i][j];
//记录每行或者每列连续字母的起始位置
if(s[i][j]!='*'&&(j==0||i==0||(s[i][j-1]=='*'&&j>0)||(s[i-1][j]=='*'&&i>0))){
num++;
n[i][j]=num;
}
}
getchar();
}
// 注意换行要求,只有两个输出之间才有空格
if(k>1)
cout<<endl;
printf("puzzle #%d:\nAcross\n",k);
//输出的时候继续遍历每行每列
for(int i=0;i<a;i++)
for(int j=0;j<b;j++)
// 判断出该点是连续字母的起始位置时,开始输出
if(s[i][j]!='*'&&((s[i][j-1]=='*'&&j>0)||j==0))
{
printf("%3d.",n[i][j]);
int l;
for(l=j;s[i][l]!='*'&&l<b;l++)
cout<<s[i][l];
cout<<endl;
j=l-1;//更新 列 的位置
}
printf("Down\n");
for(int i=0;i<a;i++)
for(int j=0;j<b;j++)
if(s[i][j]!='*'&&((s[i-1][j]=='*'&&i>0)||i==0))
{
printf("%3d.",n[i][j]);
for(int l=i;s[l][j]!='*'&&l<a;l++)
cout<<s[l][j];
cout<<endl;
}
k++;
}
return 0;
}