“伯爵说”序列如下:1,11,21,1211,111221, \ldots1,11,21,1211,111221,…。其1
读作one 1
或者11
。11
读作two 1s
或者21
。21
读作one 2, one 1
或者1211
。
输入格式
多组输入,读到文件结束。每组输入给定一个整数 n(1 \leq n \leq 30)n(1≤n≤30)。
输出格式
输出第 nn 个序列。注意,整数序列以字符串的形式表示。
样例输入
6
样例输出
312211
#include<string.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
void convert(char *s)
{
unsigned long size=strlen(s);
char digit[size];
int fre[size];
digit[0]=s[0];//digit的首位初始化
fre[0]=1;//fre的首位初始化
int k=0;//k是digit的数字个数
for(int i=1;i<size;i++){
if(s[i]==s[i-1]){//这个字符和上一个字符相同
fre[k]++;
}
else{//不相同,则保存字符,并且记录次数为1
k++;
digit[k]=s[i];
fre[k]=1;
}
}
for(int i=0;i<size;i++) s[i]='\0';
for(int i=0;i<=k;i++){
s[2*i]=fre[i]+'0';
s[2*i+1]=digit[i];
}
}
int main()
{
int n;
while(cin>>n){
char s[10000]={'1'};
for(int i=0;i<n-1;i++) {
convert(s);
}
cout<<s<<endl;
}
return 0;
}
思路:写出变换的函数:从前向后遍历数组,用digit保存此时遍历到的数字,用fre保存这个数字出现的次数。每次遍历都与前一个字符比较,若字符相同,则fre++,否则digit保存新的字符,对应的新fre为1。在main函数中,根据输入的n,处理n-1次“1”即可。
总结:
这道题花费了特别久的时间……遇到了很多问题。
1、我最初的思路是用一个f数组保存1~30以内所有的“伯爵说”数字,然后根据n对应输出,但是提示超时或者栈溢出。后来改进,每次都对上次的做变换,这样只要保存两个数字即可,解决了这个问题。
2、我用string &s作为convert函数的输入变量,用s+=fre和s+=digit来保存字符,仍然提示栈溢出,只能保存1~7之内的数字。因为这个问题花费了很长时间,后来思考可能是因为+=表示将字符并在原先字符之后,原先的字符空间没有释放,这样占了非常多的内存所以没通过。但是使用s.empty()或者对s[i]='\0',都没有解决这个问题。没有办法。参考了其他人的代码后,将string类型改为了char *作为convert函数的输入变量,不使用+=,而是对每个字符用fre和digit赋值。解决了这个问题。
3、在main函数里面,char s[10000]的申明我放在了while语句之外,尽管在每次cout<<s后都对s重新初始化,仍然没有得到理想的结果,不知道原因出在哪里,只好把char s[10000]的申明放在了while之内,解决了这个问题。
唉,感觉我的基础知识还是非常匮乏的,大一学的C++都忘的干干净净的了,还自信地没带回来书。等回学校了要看C++的书。