Crossword Answers

本文介绍了一种字谜游戏的解决方案,详细解释了如何通过编程来处理字谜网格,找到所有横向和纵向的单词,并按定义编号输出这些单词。文章提供了一个示例程序,展示了如何根据特定规则对网格进行编号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A crossword puzzle consists of a rectangular grid of black and white squares and two lists of definitions (or descriptions).

One list of definitions is for ``words" to be written left to right across white squares in the rows and the other list is for words to be written down white squares in the columns. (A word is a sequence of alphabetic characters.)

To solve a crossword puzzle, one writes the words corresponding to the definitions on the white squares of the grid.

The definitions correspond to the rectangular grid by means of sequential integers on ``eligible" white squares. White squares with black squares immediately to the left or above them are ``eligible." White squares with no squares either immediately to the left or above are also ``eligible." No other squares are numbered. All of the squares on the first row are numbered.

The numbering starts with 1 and continues consecutively across white squares of the first row, then across the eligible white squares of the second row, then across the eligible white squares of the third row and so on across all of the rest of the rows of the puzzle. The picture below illustrates a rectangular crossword puzzle grid with appropriate numbering.

An ``across" word for a definition is written on a sequence of white squares in a row starting on a numbered square that does not follow another white square in the same row.

The sequence of white squares for that word goes across the row of the numbered square, ending immediately before the next black square in the row or in the rightmost square of the row.

A ``down" word for a definition is written on a sequence of white squares in a column starting on a numbered square that does not follow another white square in the same column.

The sequence of white squares for that word goes down the column of the numbered square, ending immediately before the next black square in the column or in the bottom square of the column.

Every white square in a correctly solved puzzle contains a letter.

You must write a program that takes several solved crossword puzzles as input and outputs the lists of across and down words which constitute the solutions.

Input

Each puzzle solution in the input starts with a line containing two integers r and c ( tex2html_wrap_inline39 andtex2html_wrap_inline41 ), where r (the first number) is the number of rows in the puzzle and c (the second number) is the number of columns.

The r rows of input which follow each contain c characters (excluding the end-of-line) which describe the solution. Each of those c characters is an alphabetic character which is part of a word or the character ``*", which indicates a black square.

The end of input is indicated by a line consisting of the single number 0.

Output

Output for each puzzle consists of an identifier for the puzzle (puzzle #1:puzzle #2:, etc.) and the list of across words followed by the list of down words. Words in each list must be output one-per-line in increasing order of the number of their corresponding definitions.

The heading for the list of across words is ``Across". The heading for the list of down words is ``Down".

In the case where the lists are empty (all squares in the grid are black), the Across and Down headings should still appear.

Separate output for successive input puzzles by a blank line.

Sample Input

2 2
AT
*O
6 7
AIM*DEN
*ME*ONE
UPON*TO
SO*ERIN
*SA*OR*
IES*DEA
0

Sample Output

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
纯洁的我一开始是不知道紫书上有翻译的,然后……,题目就是一个字谜,然后按横向纵向输出单词,看了看样例大概能yy出来。
然后就是模拟,题目里面也说了,首先,第一行都是有数字的,然后就是左面或者上面是黑色的格子也有数字,按照这个规律对格子赋值就好了,最后按行或列找标记的数字输出就好了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;
string a[15];
int dp[15][15];
int main()
{
	int i, j, m, n, ans, r, c, cnt, leap, p, k;
	p = 1;
	while (scanf("%d", &r) != EOF)
	{
		if (r == 0)break;
		scanf("%d", &c);
		for (i = 0; i < r; i++)
			cin >> a[i];
		for (i = 0; i < r;i++)
		for (j = 0; j < c; j++)
		{
			dp[i][j] = 0;
		}
		cnt = 1; leap = 0;
		for (i = 0; i < c; i++)
		{
			if (a[0][i] == '*')
				leap = 0;
			else if (leap == 0){
				dp[0][i] = cnt++;
				leap = 1;
			}
			else if (leap == 1){
				dp[0][i] = cnt++;
				leap = 1;
			}
		}
		for (i = 1; i < r; i++)
		{
			for (j = 0; j < c; j++)
			{
				if (a[i][j] == '*')continue;
				else if (j >= 1 && a[i][j - 1] == '*')
				{
					dp[i][j] = cnt++;
				}
				else if (j == 0 && a[i][j] != '*')
					dp[i][j] = cnt++;
				else if (a[i - 1][j] == '*')
					dp[i][j] = cnt++;
			}
		}
		if (p != 1)
			cout << endl;
		cout << "puzzle #" << p << ":" << endl;
		p++;
		cout << "Across" << endl;
		for (i = 0; i < r; i++)
		{
			for (j = 0; j < c; )
			{
				if (dp[i][j])
				{
					if (dp[i][j] < 10)
						cout << "  " << dp[i][j] << ".";
					else
						cout << " " << dp[i][j] << ".";
					k = 0;
					while (j + k < c&&a[i][j + k] != '*')
					{
						cout << a[i][j + k];
						k++;
					}
					j = j + k;
					cout << endl;
				}
				else j++;
			}
		}
		cout << "Down" << endl;
		for (i = 0; i < c; i++)
		{
			if (dp[0][i])
			{
				if (dp[0][i] < 10)
					cout << "  " << dp[0][i] << ".";
				else
					cout << " " << dp[0][i] << ".";
				j = 0;
				while (j < r&&a[j][i] != '*')
				{
					cout << a[j][i];
					j++;
				}
				cout << endl;
			}
		}
		for (i = 1; i < r; i++)
		{
			for (j = 0; j < c; j++)
			{
				if (dp[i][j] && a[i - 1][j] == '*')
				{
					if (dp[i][j] < 10)
						cout << "  " << dp[i][j] << ".";
					else
						cout << " " << dp[i][j] << ".";
					k = 0;
					while (i + k < r&&a[i + k][j] != '*')
					{
						cout << a[i + k][j];
						k++;
					}
					cout << endl;
				}
			}
		}
	}
	return 0;
}


<think>好的,用户现在想解决UVA232问题,也就是“纵横字谜”(Crossword Answers)的题目,需要用C++来实现。首先,我需要回忆一下这个题目的具体要求。根据UVA的题目描述,通常这个题目是要求处理一个网格,找到所有符合条件的起始格子,并按照顺序编号,然后分别输出横向和纵向的单词。 首先,用户提供的引用内容中有几个C++的例子,比如处理快乐数、丑数、马拉松接力赛和盒子问题。虽然这些例子可能不直接相关,但可以参考其中的编程风格和技巧。例如,引用1中的代码使用了输入输出优化(ios::sync_with_stdio(false); cin.tie(0);),这在处理大规模输入时很重要,可能对UVA232也有帮助,因为在线评测系统通常对输入输出效率有较高要求。 接下来,用户提到的UVA232问题,我需要先明确题目要求。根据UVA232的描述,题目大致是给定一个r行c列的网格,其中有些格子是黑色(用'*'表示),其余是字母。任务是找出所有符合条件的起始格子,即左边或上边是边界或黑色格子的白格,并为它们编号。然后输出所有横向和纵向的单词,按起始格子的编号顺序排列。 接下来,我需要考虑如何设计数据结构。可以用二维数组存储网格,另外两个二维数组来记录每个格子的编号。编号需要从1开始递增,每个符合条件的起始格子分配一个编号。然后遍历网格,横向和纵向分别收集单词。 注意题目中的细节,比如横向单词是从左到右,直到遇到黑色格子或边界;纵向单词是从上到下。同时,起始格子必须满足左边或上边是边界或黑色格子,但横向和纵向可能有不同的起始条件。例如,横向的起始格子需要左边是边界或黑色,而纵向的起始格子需要上边是边界或黑色。因此,同一个格子可能同时是横向和纵向的起始点,需要分别处理。 接下来,考虑如何实现编号。可以遍历每个格子,检查是否是横向起始或纵向起始。如果是其中之一,则分配编号。需要注意的是,同一个格子可能同时是横向和纵向的起始点,但编号只需分配一次,并且编号是递增的,按照行优先的顺序。 然后,收集横向单词和纵向单词。对于每个横向起始格子,向右遍历直到遇到黑色或边界,将字母拼接成单词。同样,对于纵向起始格子,向下遍历。需要确保每个单词至少有两个字母,因为单个字母的格子不算单词。 在实现时,需要注意输入格式。每个测试用例可能由多个网格组成,需要正确处理输入输出。例如,每个网格处理完后输出其答案,并且不同网格之间可能有空行分隔,但最后一个测试用例后不能有多余的空行。 另外,输入中的网格可能包含大小写字母,但题目通常要求处理时不区分大小写,或者按原样输出,需要确认题目具体要求。根据UVA232的标准,通常保持原样即可。 现在,参考用户提供的引用中的代码结构,比如引用1中的函数分解,可以设计一个结构,将功能模块化。例如,读取网格、分配编号、收集横向单词、收集纵向单词等步骤分开处理。 还需要注意边界条件,例如网格的第一行或第一列,此时左边或上边是边界,直接视为起始条件。此外,黑色格子不参与任何单词。 在代码实现中,可以使用两个二维数组来记录横向和纵向的起始编号,或者使用一个编号数组,只要满足条件就分配编号,无论横向还是纵向。但需要注意,同一个格子可能被多次检查,但编号只需分配一次,按照行优先的顺序递增。 例如,遍历网格时,按行优先顺序检查每个格子是否为横向或纵向的起始点。如果是,并且尚未分配编号,则分配当前编号并递增。这样可以确保每个起始格子有唯一的编号,并按照正确的顺序排列。 接下来,收集单词时,需要按照编号的顺序输出。横向单词和纵向单词分别存储在一个列表中,按起始编号排序后输出。或者,可以在遍历时按顺序收集,确保处理顺序正确。 对于输入输出的优化,可以像引用1中那样使用ios::sync_with_stdio(false);和cin.tie(0);来加快C++的输入输出速度,这在处理大规模输入时很重要,尤其是在线评测系统中。 测试样例方面,需要构造一些测试用例来验证代码的正确性。例如,一个简单的2x2网格,其中有一个黑色格子,检查编号是否正确,单词是否正确输出。或者更复杂的网格,确保所有起始点都被正确识别,单词按顺序排列。 此外,还需要处理多个测试用例的情况,直到输入结束。每个用例输出对应的结果,格式正确,尤其是题目中常有的要求,比如在每个网格输出后跟一个空行,除了最后一个。 最后,代码的结构应该清晰,变量命名有意义,注释适当,方便理解和调试。例如,使用grid存储原始网格,number数组存储编号,横向和纵向的单词分别收集到不同的vector中,按编号排序后输出。</think>### UVA232 纵横字谜 C++ 解法详解 #### **问题理解** 题目要求处理包含字母和星号(`*`)的网格,完成以下任务: 1. 找出所有**有效起始格**(满足左侧/上侧是边界或星号) 2. 按行优先顺序为起始格编号 3. 输出所有横向单词(按编号顺序) 4. 输出所有纵向单词(按编号顺序) #### **核心算法步骤** ```cpp #include <iostream> #include <vector> #include <cstring> using namespace std; int r, c, cnt; char grid[12][12]; int number[12][12]; vector<pair<int, string>> across, down; // 判断是否为横向起始格 bool isAcrossStart(int i, int j) { return (j == 0 || grid[i][j-1] == '*') && grid[i][j] != '*'; } // 判断是否为纵向起始格 bool isDownStart(int i, int j) { return (i == 0 || grid[i-1][j] == '*') && grid[i][j] != '*'; } // 收集横向单词 void collectAcross(int i, int j) { string word; int num = number[i][j]; while (j < c && grid[i][j] != '*') { word += grid[i][j]; j++; } if (word.length() >= 1) across.push_back({num, word}); } // 收集纵向单词 void collectDown(int i, int j) { string word; int num = number[i][j]; while (i < r && grid[i][j] != '*') { word += grid[i][j]; i++; } if (word.length() >= 1) down.push_back({num, word}); } int main() { ios::sync_with_stdio(false); cin.tie(0); int cases = 0; while (cin >> r >> c && r) { // 初始化 memset(number, 0, sizeof(number)); across.clear(); down.clear(); cnt = 1; // 读取网格并编号 for (int i = 0; i < r; ++i) { for (int j = 0; j < c; ++j) { cin >> grid[i][j]; if (isAcrossStart(i, j) || isDownStart(i, j)) { number[i][j] = cnt++; } } } // 收集单词 for (int i = 0; i < r; ++i) { for (int j = 0; j < c; ++j) { if (number[i][j] && isAcrossStart(i, j)) { collectAcross(i, j); } if (number[i][j] && isDownStart(i, j)) { collectDown(i, j); } } } // 输出结果 if (cases) cout << "\n"; cout << "puzzle #" << ++cases << ":\n"; cout << "Across\n"; for (auto &p : across) cout << (p.first < 10 ? " " : " ") << p.first << "." << p.second << "\n"; cout << "Down\n"; for (auto &p : down) cout << (p.first < 10 ? " " : " ") << p.first << "." << p.second << "\n"; } return 0; } ``` #### **技术要点解析** 1. **输入优化** 使用`ios::sync_with_stdio(false);`和`cin.tie(0);`提升IO速度[^1] 2. **起始格判定** - 横向起始:左侧是边界或`*` - 纵向起始:上侧是边界或`*` 3. **编号策略** 采用行优先遍历顺序,保证编号递增正确性 4. **单词收集技巧** - 横向收集:向右遍历直到遇到`*`或边界 - 纵向收集:向下遍历直到遇到`*`或边界 5. **格式化输出** 使用三元运算符处理编号对齐问题:`p.first < 10 ? " " : " "` #### **测试用例示例** 输入: ``` 2 2 AT *O 0 ``` 输出: ``` puzzle #1: Across 1.AT 3.O Down 1.A 2.TO ``` #### **常见问题处理** 1. **重复编号问题** 同一个格子可能同时是横向和纵向起始点,但通过统一编号逻辑避免重复 2. **单字母单词过滤** 通过`if (word.length() >= 1)`确保收集有效单词 3. **多测试用例格式控制** 使用`if (cases) cout << "\n";`确保输出间隔符位置正确
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值