题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4148
S(1)=1,
S(2)=11,
S(3)=21,
S(4)=1211,
S(5)=111221,
S(6)=312211,
找规律 后一行由前一行推出
S(5) 由 3个1,2个2,1个1组成,所以S(6)=313311
继续推 S(7) = 13112321
网上有很多精简巧妙的算法,为了方便理解这里用最朴实,最易理解的代码实现:
s[30][20000] 存储S(1)到S(30), ps下标减一;
初始化为全部是-1, -1代表该数组元素未使用
循环由前一位统计处下一位的数。
#include <cstring>
#include <iostream>
using namespace std;
int s[30][20000];
int numBits(int n) {
int res = 1;
while (n > 9) {
n /= 10;
res++;
}
return res;
}
int main() {
memset(s, -1, sizeof(s));
for (int i = 0; i < 30; i++) {
if (i == 0) {
s[i][0] = 1;
} else {
int curNum = s[i - 1][0]; //当前数字
int cnt = 1; //当前数字出现次数
int pos = 0; //第i个数组已经使用到的下标
int j = 1;
while (s[i - 1][j - 1] != -1) {
if (curNum == s[i - 1][j]) {
cnt++;
} else {
int bits = numBits(cnt);
int tmpBits=bits;
while (cnt > 9) {
s[i][pos + tmpBits - 1] = cnt % 10;
cnt /= 10;
tmpBits--;
}
s[i][pos] = cnt;
pos += bits;
s[i][pos] = curNum;
pos++;
curNum = s[i - 1][j];
cnt = 1;
}
j++;
}
}
}
int n;
while (cin >> n && n) {
int len = 0;
while (s[n - 1][len] != -1) {
len++;
}
cout << len << endl;
}
}