蓝桥杯 省模拟赛2 摆动数组
题目
解题思路
我的解题思路参考了这位大佬的思路,非常感谢https://qiguanjie.blog.csdn.net/article/details/105622530
我从列表看规律的角度来讲解一下:
k\n | 1 | 2 | 3 |
---|---|---|---|
1 | 1 | 0 | 6 |
2 | 1 | 1 | 5 |
3 | 1 | 2 | 3 |
4 | 1 | 3 | 0 |
先看上面的这个列表,坐标(n, k)代表第n个位置填写第k个数,可以有多少种符合题意的数列,由上面的大佬第一题解法提供的思路,我们看出
当i为奇数时,根据题意,奇数项是要比前一项大,则我们的第i位数的选择数为j时,我们可以组成的序列的数量为:第i-1位时选择,数为1到j-1的和,即dp[i][j] = dp[i-1][1] + dp[i-1][2] + … + dp[i-1][j-1]。
当i为偶数时,根据题意,偶数项要比前一项小,则我们的第i位数为j时,我们可以组成的序列的数量为:第i-1位时,数为j+1到n的和,即dp[i][j] = dp[i-1][j+1] + dp[i-1][j+2] + … + dp[i-1][n]。
————————————————
版权声明:本文为CSDN博主「亓官劼」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://qiguanjie.blog.csdn.net/article/details/105622530
这样的计算复杂度为显然超时,因为可以看出有很多重复的计算,但是就我列举的那个表格而言,我们可以吧规律进一步简化为:
if(i%2)
{
dp[n+1-j][i]=dp[n-j+2][i-1]+dp[n-j+2][i];
}
else
{
dp[j][i]=dp[j-1][i-1]+dp[j-1][i];
}
就计算方法而言,和那位博主上面的一样,但是我精简了计算,使复杂程度变为了O(kn)
最后答案只需将表格最后一列所有数相加即可,
程序实现
总体代码为
#include<iostream>
using namespace std;
int dp[1010][1010];
int main()
{
int n,k;
long long sum=0;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
dp[i][1]=1;
}
for(int i=2;i<=k;i++)
{
for(int j=1;j<=n;j++)
{
if(i%2)
{
dp[n+1-j][i]=dp[n-j+2][i-1]+dp[n-j+2][i];
}
else
{
dp[j][i]=dp[j-1][i-1]+dp[j-1][i];
}
}
}
for(int i=1;i<=n;i++)
{
sum+=dp[i][k];
}
cout<<sum;
return 0;
}
本人能力有限,如有错误的,希望各位大佬指出,一起进步!