蓝桥杯_算法训练_ALGO12_摆动序列

问题描述
  如果一个序列满足下面的性质,我们就将它称为摆动序列:
  1. 序列中的所有数都是不大于k的正整数;
  2. 序列中至少有两个数。
  3. 序列中的数两两不相等;
  4. 如果第i – 1个数比第i – 2个数大,则第i个数比第i – 2个数小;如果第i – 1个数比第i – 2个数小,则第i个数比第i – 2个数大。
  比如,当k = 3时,有下面几个这样的序列:
  1 2
  1 3
  2 1
  2 1 3
  2 3
  2 3 1
  3 1
  3 2
  一共有8种,给定k,请求出满足上面要求的序列的个数。
输入格式
  输入包含了一个整数k。(k<=20)
输出格式
  输出一个整数,表示满足要求的序列个数。
样例输入
3
样例输出

8


自己从来没有做过动态规划的题目,之前接触动态规划还是为了过算法的考试。所以说,坑总是要填的,迟早的事情,加油!

言归正传,这个题是要求满足题目的序列个数。刚开始看到这个题,我的想法是,先自己试着手动做做,看看能不能发现什么。果然被我试出来了。动态规划核心是构造一个表,根据已有的表格内容得到我们想要的结果。构造表的过程并不是一下子就成功的,期间我共想了两种方式来构造,但是后来发现第一种方式是没有办法构造表的,因为在构造的过程中发现表间元素没有什么关联,所以换个思路,用另一个方法进行构造(有点递归的意思,但是并不是递归,也就是说当前数据依靠表格的之前的数据),给大家看一下我的表格构造:

摆动序列动规表格
 002003004005006007008
002200
0
0
0
0
0036200000 
00412820
0
0
0
00520201020
0
0
0063040301220
0
007427070421420
0085611214011256162

通过这个表格不难发现规律。

(1)这个表格为什么从2开始呢?

因为根据题目要求,每行至少两个正整数,所以不存在0和1的情况;

(2)这个表格根据什么构成?

是根据k值的不同,来看对应情况下的可能的序列个数。举个例子:当k等于3的时候,考虑如果只有俩个数组成,可能多少种情况,如果有3个数组成,可能多少种情况。填入到表格中即可。如果学过排列组合,那不难发现彼此之间的关系,也因此得到了这个表格。

(3)有人可能通过排列组合的方式,不用构建表格就可以得到最后的结果,那还有必要建表格吗?

有必要。如果是排列组合,举例来说:k=8时,


这样也可以算出最后的结果,但是乘法比加法的运算速度慢,此外,如果这么计算,其实重复性挺大的,利用表格,相当于记录了路径,之前算的东西可以直接拿来用,不用重新进行计算,更为快捷方便!


好,给大家看一下代码,不到之处还希望大家可以批评指正:

#include<iostream>
using namespace std;
int main()
{
	int k;
	int a[21][21];
	long result = 0;
	cin>>k;
	for(int i = 2; i <= k; i++)
	{
		a[i][i] = 2;
		a[i][2] = i*(i-1);
		for(int j = 3; j < i; j++)
		{
			a[i][j] = a[i-1][j]+a[i-1][j-1];
		}
	}
	for(int i = 2; i <= k; i++)
	{
		result += a[k][i];
	}
	cout<<result;
	return 0;	
} 

END。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

allein_STR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值