纵横字谜的答案(Crossword Answers)

Posted vincent-yuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了纵横字谜的答案(Crossword Answers)相关的知识,希望对你有一定的参考价值。

题目

输入一个r行c列(1<=r, c<=10)的网格,黑格用 * 表示,每个白格都填有一个字母。

如果一个白格的左边相邻位置或者上边相邻位置没有白格(可能是黑格,也可能出了网格边界),

则称这个白格是一个起始格。

首先把所有起始格按照从上到下,从左到右的顺序编号为1,2,3,... ,如图

技术图片

 

 

 接下来要找出所有横向单词(Across)。这些单词必须从一个起始格开始,

向右延伸到一个黑格的左边或者整个网格的最右边列。最后找出所有的竖向单词(Down)。

这些单词必须从一个起始格开始,向下延伸到一个黑格的上边或者整个网格的最下行。

输入样例

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

分析

用s[][] 存储r行c列的字符,lable[][]用来标记对应位置起始格的编号;

1.检测起始格

2.检测横向单词和竖向单词

 

c实现

#include<stdio.h>
#include<string.h>
#define maxn 12

int main(){
    //r行,c列 
    int r,c;
    
    while(scanf("%d",&r)&&r){
        scanf("%d",&c);
        char s[r][c];
        //依次输入每行的数据 
        for(int i=0;i<r;i++)
        {
            scanf("%s",s[i]);
        }
        //用来标记起始格的序号1,2,... 
        int lable[r][c];
        int count=0;
        //检测标记对应位置的起始格 
        for(int i=0;i<r;i++){
            for(int j=0;j<c;j++)
            {
                //起始格:首先不是黑格,然后为边界或者(左边相邻位置或者上边相邻位置没有白格) 
                if(s[i][j]!=*&&(i==0||j==0||s[i-1][j]==*||s[i][j-1]==*))
                {
                    lable[i][j] = (++count);
                }else{
                    lable[i][j] = 0;//非起始格标记为0 
                }
            }
        }
        
        //横向输出 
        printf("Across
");
        for(int i=0;i<r;i++)
        {
            for(int j=0;j<c;j++)
            {
                //横向单词满足的条件:首先该位置是起始格,然后左边界或左边相邻位置为黑格 
                if(lable[i][j]>0&&(j==0||s[i][j-1]==*))
                {
                    printf("%d.%c",lable[i][j],s[i][j]);
                    for(int k=j+1;k<c;k++){
                        if(s[i][k]==*){
                            break;
                        }else{
                            printf("%c",s[i][k]);
                        }
                    }
                    printf("
");
                }
            }
        }
        printf("Down
");
        for(int i=0;i<r;i++){
            for(int j=0;j<c;j++){
                //竖向单词满足的条件:首先该位置是起始格, 然后为上边界或者上边相邻位置为黑格 
                if(lable[i][j]>0&&(i==0||s[i-1][j]==*))
                {
                    printf("%d.%c",lable[i][j],s[i][j]);
                    for(int k=i+1;k<r;k++){
                        if(s[k][j]==*){
                            break;
                        }else{
                            printf("%c",s[k][j]);
                        }
                    }
                    printf("
");
                }
            }
        }
    }
    
    return 0;
}

 

以上是关于纵横字谜的答案(Crossword Answers)的主要内容,如果未能解决你的问题,请参考以下文章

UVa 232 - Crossword Answers

UVA232-纵横字谜的答案

uva 232 Crossword Answers

[算法竞赛入门经典] Crossword Answers ACM/ICPC World Finals 1994,UVa232

Codeforces 1194F Crossword Expert

字谜/部分字谜检测算法找到不正确的答案