【题目描述】
Jam是个喜欢标新立异的科学怪人。他不使用阿拉伯数字计数,而是使用小写英文字母计数,他觉得这样做,会使世界更加丰富多彩。在他的计数法中,每个数字的位数都是相同的(使用相同个数的字母),英文字母按原先的顺序,排在前面的字母小于排在它后面的字母。我们把这样的“数字”称为Jam数字。在Jam数字中,每个字母互不相同,而且从左到右是严格递增的。每次,Jam还指定使用字母的范围,例如,从2到10,表示只能使用{b,c,d,e,f,g,h,i,j}这些字母。如果再规定位数为5,那么,紧接在Jam数字“bdfij”之后的数字应该是“bdghi”。(如果我们用U、V依次表示Jam数字“bdfij”与“bdghi”,则U<V,且不存在Jam数字P,使U<P<V)。你的任务是:对于从文件读入的一个Jam数字,按顺序输出紧接在后面的5个Jam数字,如果后面没有那么多Jam数字,那么有几个就输出几个。
【输入】
有2行,第1行为3个正整数,用一个空格隔开:
s t w (其中s为所使用的最小的字母的序号,t为所使用的最大的字母的序号。w为数字的位数,这3个数满足:1≤s第2行为具有w个小写字母的字符串,为一个符合要求的Jam数字。
所给的数据都是正确的,不必验证。
【输出】
最多为5行,为紧接在输入的Jam数字后面的5个Jam数字,如果后面没有那么多Jam数字,那么有几个就输出几个。每行只输出一个Jam数字,是由w个小写字母组成的字符串,不要有多余的空格。
【输入样例】
2 10 5
bdfij
【输出样例】
bdghi
bdghj
bdgij
bdhij
befgh
【解题思路】
解题思路如下:
-
读取输入:读取输入的最小字母序号
start
、最大字母序号end
和数字的位数len
,以及当前的 Jam 数字num
。 -
外层循环:使用一个循环控制输出的 Jam 数字数量,最多输出 5 个。
-
内层循环:从 Jam 数字的最后一个字符开始向前枚举可能的变动位。
-
计算最大值:对于每个位置
j
,计算该位置可以取到的最大值tmp
。 -
判断可行性:检查当前位
num[j]
加 1 是否小于等于tmp
,如果是,则找到了下一个Jam数字的当前位。 -
更新Jam数字:将
num[j]
加 1,并更新j
之后的所有位,确保 Jam 数字严格递增。 -
输出Jam数字:输出更新后的 Jam 数字。
-
结束条件:如果已经找到下一个Jam数字,则跳出内层循环,继续寻找下一个。
-
重复过程:重复步骤 3 到 8,直到输出了 5 个 Jam 数字或者已经没有更多的 Jam 数字可以生成。
【代码实现】
#include<bits/stdc++.h>
using namespace std;
char num[35]; // 存储输入的Jam数字
int main() {
int start, end, len;// 读取字母范围的起始和结束序号,以及数字的位数
cin>>start>>end>>len;
cin>>num;// 读取输入的Jam数字字符串
// 尝试输出5个Jam数字
for (int i = 1; i <= 5; i++) {
// 从Jam数字的最后一个字符开始向前枚举变动位
for (int j = len - 1; j >= 0; j--) {
int tmp = 'a' + (end - (len - j)); // 计算当前位可以取到的最大值
// 判断当前位加1是否小于等于tmp,即是否可行
if (num[j] + 1 <= tmp) {
num[j] += 1; // 将当前位加1
// 对齐后续位,确保Jam数字严格递增
for (int k = j + 1; k < len; k++) {
num[k] = num[j] + (k - j);
}
cout<<num<<endl;// 输出新的Jam数字
break; // 找到下一个Jam数字后,跳出内层循环
}
}
}
return 0;
}