uva 232 Crossword Answers

本文介绍了一道UVA-232填字游戏问题的解决方法,通过判断起始格子并利用结构体存储结果,最终按ID排序输出横向和纵向单词。

https://vjudge.net/problem/UVA-232

题意:

输入一个r行c列的网格,黑格用“*”来表示,每个白格都填有一个字母。如果一个白格的左边或者上边的相邻位置没有白格(可能是黑格,也可能没有格子),则这个白格式一个起始格子。首先把所有的起始格子按照从上到下,从左到右的编号为1,2,3,……。找出所有的横向单词,这些单词必须从一个起始格子开始,这些单词必须从一个起始格子开始,向右延伸到一个黑格的左边或者整个网格的最右列。竖向单词类似。

思路:

简单模拟,不过需要注意起始格子的判断情况,其实也不难,用一个结构体保存结果,最后按照id排序就可以了。

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <vector>
  4 #include <string>
  5 #include <iostream>
  6 #include <algorithm>
  7 using namespace std;
  8 
  9 struct node
 10 {
 11     int id;
 12     string s;
 13 };
 14 
 15 char a[15][15];
 16 int b[15][15];
 17 
 18 vector<node> row;
 19 vector<node> col;
 20 
 21 bool cmp(node aa,node bb)
 22 {
 23     return aa.id < bb.id;
 24 }
 25 
 26 int main()
 27 {
 28     int cas = 0;
 29 
 30     int r,c;
 31 
 32     while (scanf("%d",&r) != EOF)
 33     {
 34         if (r == 0) break;
 35 
 36         row.clear();col.clear();
 37 
 38         scanf("%d",&c);
 39 
 40         int bh = 1;
 41 
 42         for (int i = 0;i < r;i++)
 43             scanf(" %s",a[i]);
 44 
 45         for (int i = 0;i < r;i++)
 46             for (int j = 0;j < c;j++)
 47         {
 48             if (a[i][j] != '*')
 49             {
 50                 if (i - 1 < 0 || j - 1 < 0)
 51                 {
 52                     b[i][j] = bh++;
 53                 }
 54                 else if (i - 1 >= 0 && a[i-1][j] != '*' && j - 1 >= 0 && a[i][j-1] != '*') continue;
 55                 else b[i][j] = bh++;
 56 
 57             }
 58         }
 59 
 60         for (int i = 0;i < r;i++)
 61         {
 62             int st = 0;
 63 
 64             while (st < c)
 65             {
 66                 string tmp;
 67 
 68                 while (a[i][st] == '*') st++;
 69 
 70                 int id = b[i][st];
 71 
 72                 for (;a[i][st] != '*' && st < c;st++)
 73                 {
 74                     tmp.push_back(a[i][st]);
 75                 }
 76 
 77 
 78                 if (tmp.size() > 0)
 79                 {
 80                     node tt;
 81                     tt.s = tmp;
 82                     tt.id = id;
 83 
 84                     row.push_back(tt);
 85                 }
 86             }
 87 
 88         }
 89 
 90 
 91         for (int j = 0;j < c;j++)
 92         {
 93             int st = 0;
 94 
 95             while (st < r)
 96             {
 97                 string tmp;
 98 
 99                 while (a[st][j] == '*') st++;
100 
101                 int id = b[st][j];
102 
103                 for (;a[st][j] != '*' && st < r;st++)
104                 {
105                     tmp.push_back(a[st][j]);
106                 }
107 
108 
109                 if (tmp.size() > 0)
110                 {
111                     node tt;
112                     tt.s = tmp;
113                     tt.id = id;
114 
115                     col.push_back(tt);
116                 }
117             }
118 
119         }
120 
121 
122         sort(row.begin(),row.end(),cmp);
123         sort(col.begin(),col.end(),cmp);
124 
125         if (cas) puts("");
126 
127         printf("puzzle #%d:\n",++cas);
128 
129         printf("Across\n");
130 
131         for (int i = 0;i < row.size();i++)
132         {
133             printf("%3d.",row[i].id);
134             cout << row[i].s << endl;
135         }
136 
137         printf("Down\n");
138 
139         for (int i = 0;i < col.size();i++)
140         {
141             printf("%3d.",col[i].id);
142             cout << col[i].s << endl;
143         }
144     }
145 
146 
147     return 0;
148 }

 

04-24
<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、付费专栏及课程。

余额充值