研究了一晚上算是找到了点点规律,发出来大家共同学习=。=
(不一定对,有错误请大佬指正)
首先,我们先手算一下n为6时所有可能的序列(当然你也可以用代码)6 1
6 1 1
6 1 2
6 1 3
6 1 3 1
6 1 3 1 1
6 1 4
6 1 4 1
6 1 4 1 1
6 1 4 1 2
6 1 4 2
6 1 4 2 1
6 2
6 2 1
6 2 2
6 2 3
6 3
6 3 1
6 3 1 1
6 3 2
6 4
6 4 1
6 4 1 1
6 4 1 2
6 5
6 6
我们可以发现:
当 4 1 的后面分支都是相同的(我也表达不明白,看图)
可以得出:
当前一个数(a)和后一个数(b)相同时,产生的结果数也是相同的
于是我们将结果数保存在一个二维数组中,下一次要用时直接取用
经过测试,有效的减少了运算量,对于n=1000也能1s内得出结果
(虽然我也不知道答案是否准确就对了,希望有做出不同思路的大佬能跟我校对下答案)
贴下我优化后的代码#include <iostream>
#include <cmath>
//#include <ctime>
using namespace std;
int buff[1001][1001];
//clock_t clSt, clEd;
int ca(int a, int b)
{
if (buff[a][b] != 0) {
//由于ab相同后续的可能性也相同,这里我直接取用之前保存的结果数
return buff[a][b];
}
int ab = abs(a - b);
int c;
int count = 1;
for (c = 1; c < ab; c++)
{
//cout << a << '\t' << b << '\t' << c << endl;
count += ca(b, c);
}
count %= 10000;//每次都对结果取余,防止溢出(可能。。。还是会溢出)
buff[a][b] = count;//保存结果
return count;
}
int main()
{
int n;
cin >> n;
//初始化
//clSt = clock();
int ret = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
buff[i][j] = 0;
}
}
//第二个数
for (int i = 1; i <= n; i++)
{
//cout << n << '\t' << i << endl;
ret += ca(n, i);
}
ret %= 10000;
//clEd = clock();
cout << ret << endl;
//double runtime = (double)(clEd - clSt) / CLOCKS_PER_SEC;
//cout << "用时:" << runtime << endl;
return 0;
}
|