DP:摆动序列

问题描述
  如果一个序列满足下面的性质,我们就将它称为摆动序列:
  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
 
思路:这个题与其说是动态规划,不如说是找规律。
1.k个数组成的k个数的摆动序列就只有两种。
2.k个数组成的2个数的摆动序列根据高二学的排列组合就是C2k*2,因为k中选2个数。
3.然后再找规律,四个数中选3个,就相当于四个数中选1个,即一共四种选法,而这每种选法构成的摆动序列只有两种,例如1 2 3 4,选1 2 3,构成的摆动序列就是2 1 3或者2 3 1,所以4选3构成8种摆动序列,然后继续推,得到一个表格就能找到其中的规律。
  2 3 4 5 6 7 8
2 2 0 0 0 0 0 0
3 6 2 0 0 0 0 0
4 12 8 2 0 0 0 0
5 20 20 10 2 0 0 0
6 30 40 30 12 2 0 0
7 42 70 70 42 14 2 0
8 56 112 140 112 56 16 2
 
 
 
 
 
 
 
 
横坐标表示k,纵坐标表示选取的个数。
所以第一列就是C2k*2,代码表示: memo[i][2] = i * i - i; 
剩下的就是 memo[i][j] = memo[i - 1][j] + memo[i - 1][j - 1] 
最后结果就是把k的那一行累加即可 res += memo[k][i]; 
代码
复制代码
 1 #include<iostream>
 2 #include<vector>
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int k;
 8 
 9     cin >> k;
10     vector< vector<int> > memo(k+1, vector<int>(k+1,0));
11     
12     for (int i = 2; i <= k; i++)
13     {
14         memo[i][2] = i * i - i;  //Cn2*2;
15     }
16 
17     for (int i = 3; i <= k; i++)
18     {
19         for (int j = 3; j <= k; j++)
20         {
21             memo[i][j] = memo[i - 1][j] + memo[i - 1][j - 1];
22         }
23     }
24 
25     int res = 0;
26     for (int i = 2; i <= k; i++)
27     {
28         res += memo[k][i];
29     }
30 
31     cout << res;
32     return 0;
33 }
复制代码

 

posted @   Xxaj5  阅读(305)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示