UVa 232 Crossword Answers

解析纵横字谜:算法与技巧
本文深入探讨了解决纵横字谜的算法与策略,包括如何从边界或特定符号开始,逐步输出横纵串。文章详细介绍了使用数组实现算法的过程,强调了预防错误的重要性,并分享了采用短路操作避免数组越界的经验。通过实例分析,读者可以掌握解决此类谜题的核心思路。

纵横字谜

大概规则是上面或左边是边界或‘*’的时候是起始格

然后分别输出横着的和竖着的串

思路嘛,从左到右从上到下依次检查,如果是起始格就把坐标存起来

本来想用个队列,发现数组就够了

然后开始敲

还有就是紫书上说的,做之前检查而不是做了之后后悔,

大多数情况下亡羊补牢总是麻烦一点的

 从今天开始爱上短路操作,再也不用担心数组越界了


#include<stdio.h>
#include<iostream>
using namespace std;

int main(){
    int n,m=0;
    int t=1;
    while(~scanf("%d",&n) && n){
        if(m) printf("\n");
        scanf("%d",&m);
        char a[12][12];
        int len=0;
        int arr[2][100]={0};
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                cin>>a[i][j];
                if(a[i][j]!='*' &&
                   ((i==0 || a[i-1][j]=='*') || (j==0 || a[i][j-1]=='*'))){
                        arr[0][len]=i;
                        arr[1][len]=j;
                        len++;
                }
            }
        }
        printf("puzzle #%d:\n",t++);
        printf("Across\n");
        for(int i=0;i<len;i++){
            if(arr[1][i]==0 || a[arr[0][i]][arr[1][i]-1]=='*'){
                printf("%3d.",i+1);
                for(int y=arr[1][i];y<m && a[arr[0][i]][y]!='*';y++)
                    printf("%c",a[arr[0][i]][y]);
                printf("\n");
            }
        }
        printf("Down\n");
        for(int i=0;i<len;i++){
            if(arr[0][i]==0 || a[arr[0][i]-1][arr[1][i]]=='*'){
                printf("%3d.",i+1);
                for(int x=arr[0][i];x<n && a[x][arr[1][i]]!='*';x++)
                    printf("%c",a[x][arr[1][i]]);
                printf("\n");
            }
        }
    }
	return 0;
}

UVa的PE判定真是。。。

<think>好的,用户现在在问关于UVA232编程问题的解决方案或解释。首先,我需要回忆一下UVA232的具体内容。UVA232题目通常是关于“纵横字谜”(Crossword Answers)的问题。题目要求生成一个数字网格,并根据行和列生成相应的单词列表。 首先,确认问题内容:UVA232要求处理一个字符网格,其中有效的起始格(即可以横向或纵向组成单词的起始位置)需要被编号,然后输出横向和纵向的单词列表。每个起始格的条件是左边或上边是边界或'#'符号,而当前位置是字母。 接下来,用户可能需要解决方案的具体步骤。通常,解决这个问题需要分为几个步骤:读取输入网格,确定每个格子的编号,生成横向和纵向的单词列表,并按顺序输出。需要注意输入输出的格式,比如编号的顺序是从左到右、从上到下,横向单词按起始编号升序排列,纵向也是如此。 然后,考虑可能的代码实现。使用二维数组存储网格,另一个二维数组存储每个格子的编号。遍历每个格子,检查是否为起始格,如果是,则分配一个递增的编号。接着,横向遍历每一行,提取连续的字母作为单词,遇到'#'或边界时分割。纵向同理,但需要按列遍历,逐行检查。 此外,需要处理输入输出格式,比如每个谜题之间的空行,但注意最后一个谜题后不应有空行。这可能容易出错,需要特别注意。 用户可能遇到的常见问题包括:编号错误、单词分割不正确、输出格式不符合要求等。例如,起始格的判断条件是否正确,是否考虑了边界情况,横向和纵向的遍历顺序是否正确,编号是否连续递增等。 最后,根据用户的问题,提供具体的代码示例和解释,确保代码结构清晰,注释到位。同时,提醒用户注意测试边界情况,例如全'#'的网格,或者只有一行或一列的情况。</think>### UVA232 Crossword Answers 问题解析 UVA232题目要求处理一个字符网格,生成满足条件的单词编号及横向(Across)、纵向(Down)的单词列表。以下是具体步骤与示例代码。 --- #### **问题核心逻辑** 1. **编号规则** 格子$(r,c)$是起始格的条件: - 当前字符为字母(非`#`) - **左侧**是边界或`#`(横向起始)**或** **上方**是边界或`#`(纵向起始) 2. **横向单词提取** 从左到右逐行扫描,遇到连续字母序列时记录起始编号和单词。 3. **纵向单词提取** 从上到下逐列扫描,同样记录起始编号和单词。 --- #### **代码实现(Python)** ```python def solve_crossword(grid): rows = len(grid) cols = len(grid[0]) numbers = [[0] * cols for _ in range(rows)] num = 1 # 步骤1:分配编号 for r in range(rows): for c in range(cols): if grid[r][c] == '#': continue # 检查是否横向或纵向起始格 left_invalid = (c == 0) or (grid[r][c-1] == '#') top_invalid = (r == 0) or (grid[r-1][c] == '#') if left_invalid or top_invalid: numbers[r][c] = num num += 1 # 步骤2:提取横向单词 across = [] for r in range(rows): word = [] current_num = 0 for c in range(cols): if grid[r][c] == '#': if word: across.append((current_num, ''.join(word))) word = [] current_num = 0 else: if numbers[r][c] != 0 and current_num == 0: current_num = numbers[r][c] word.append(grid[r][c]) if word: # 行末剩余字母 across.append((current_num, ''.join(word))) # 步骤3:提取纵向单词 down = [] for c in range(cols): word = [] current_num = 0 for r in range(rows): if grid[r][c] == '#': if word: down.append((current_num, ''.join(word))) word = [] current_num = 0 else: if numbers[r][c] != 0 and current_num == 0: current_num = numbers[r][c] word.append(grid[r][c]) if word: down.append((current_num, ''.join(word))) return across, down ``` --- #### **关键注意事项** 1. **输入格式** 输入以`0 0`结束,每个谜题之间用空行分隔,但**最后一个谜题后无空行**。 2. **输出顺序** - 横向单词按编号升序排列 - 纵向单词按编号升序排列 3. **测试案例示例** 输入: ``` 2 2 A# #B 0 0 ``` 输出: ``` Puzzle #1: Across 1.A 3.B Down 1.A 2.B ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值