UVA232 纵横字谜的答案 Crossword Answers 题解
OoXiao_QioO · · 题解
前言
非常好的一道模拟题。
美中不足的是这很恶心的输出格式,给我们增加了许多的难度,而且题目给的格式和 pdf 里面的差多了,坑了我好多次。
思路
从最棘手的部分——输出开始讲解。
我们可以给整体输出划
分别是小数据的编号、输出字符前的序号以及输出的串。
如下图
其中第一、三部分是更具题意输出的,主要是第二部分,它到底在干什么呢?说是序号,它也不连续啊。此时我们返回题面,通过研究(指我找了半个小时才找到的规律)发现一个规律:第三部分的第一个字符满足一下其一,就可以使编号增加。
-
处于第一行。
-
处于第一列。
-
左边是字符
* 。 -
上面是字符
* 。
只需在程序里判断即可。
解决了输出的问题,接下来就是如何找出第三部分了。
其实也很简单,一个不为 Across,那么横向输出,直到字符为
分析到这里了,想必大家都有思路了,下面就给大家放代码解释。
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
//定义变量
int n,m,i,j,p=0,cnt,t,a[101][101];//p 为测试样例的编号,a 数组的用处后面会讲
char s[101][101];
while(1)//一直输入
{
//多测不清空,爆零两行泪!!
for(i=1;i<=100;i++)
for(j=1;j<=100;j++)
a[i][j] = 0;
//测试样例编号 +1。
p++;
cin>>n;//输入行。
if(n==0)//观察输入,发现末尾输入的 0, 只有一个,那我们先输入 n,判断是否为 0 就可以了。
return 0;
cin>>m;
if(p>1)//细腻的操作 1:上一次操作的末尾加上换行。
puts("");
getchar();//读掉行末可恶的空格。
//输入字符二位数组
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
cin>>s[i][j];
//第一部分输出。
printf("puzzle #%d:\n",p);
puts("Across");
//cnt 就是第二部分的序号。
cnt = 0;
for(i=1;i<=n;i++)
{
t = 0;//t 是一个输出序号的重要基准。
for(j=1;j<=m;j++)
{
if(s[i][j]=='*')
continue;
//满足其一即可。
if(i==1||s[i-1][j]=='*'||j==1||s[i][j-1]=='*')
{
cnt++;//序号 +1。
//a 数组的妙用:存放起始格的位置,这样纵向输出就不用重新统计了。
a[i][j] = cnt;//标记初始格。
if(j>=t)
{
printf("%3d.",cnt);
int k = j;//不能用 j 查找,不然就会使变量错乱。
while(k<=m&&s[i][k]!='*')//一直查找,直到字符不为 “* ”。
{
putchar(s[i][k]);//输出
k++;
}
t = k;
puts("");
}
}
}
}
puts("Down");//输出一部分。
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(a[i][j])//如果此时是初始格的位置。
{
printf("%3d.",a[i][j]);//输出序号。
int k = i;
while(k<=n&&s[k][j]!='*')//和横向查找类似
{
putchar(s[k][j]);
a[k][j] = 0;
k++;
}
puts("");
}
}
}
}
return 0;
}