2020蓝桥杯A组模拟试题二第8题摆动序列(自写)
本文所写DFS算法的时间复杂度呈指数型,数据规模超过10,10,程序运行时间就很长了,可探寻其他解法(动态规划)
仅供学习
##问题描述:如果一个序列的奇数项都比前一项大,偶数项都比前一项小,则称为一个摆动数列
即a[2i]<a[2i-1],a[2i+1]>a[2i] ,数列可以只有一个数,该数为满足条件的任意值
求长度为 m ,每个数都是 [1,n] 之间的正整数的摆动序列一共有多少个
##输入格式:输入一行包含两个整数 m,n
##输出格式:输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数
##样例输入
3 4
##样例输出
14
##样例说明
以下是符合要求的摆动序列:
2 1 2
2 1 3
2 1 4
3 1 2
3 1 3
3 1 4
3 2 3
3 2 4
4 1 2
4 1 3
4 1 4
4 2 3
4 2 4
4 3 4
##数据规模:1 <= n,m <= 1000
解题思路:DFS深度优先遍历,用栈来记录遍历的过程,每往下深一个层次就入栈,回溯则退栈, 按序列的先后顺序入栈,将序列的第一个数入栈,然后进入下一层,然后再入栈进入下一层,循环直到序列长度达到要求则计数加1(即找到一个可行解)并回溯,若下一层次没有满足条件的结果则直接回溯,直到将所有可行解找到。
第一层:序列长度为1;(1,2,3,…,n)
第二层:序列长度为2;(<2,1>,< 3,1>,< 3,2>,…,<n,n-1>)
第三层:序列长度为3:(<2,1,2>,<2,1,3>,<2,1,4>,…,<n,n-1,n>)
…
第 n层:序列长度为n:(<2,1,2,1,…>,…,<n,n-1,n,n-1,…>)
可看作是一个树状结构
C++程序:
/*******************************************************************************
* Copyright (C): @Jiawei
* FileName: SwingSequence.cpp
* Author: @Jiawei
* Email: 1969444305@qq.com
* Date: 2020/05/11
* Version: A001(依次为A001、A002、A003 … B001、B002、B003 …)
**问题描述:如果一个序列的奇数项都比前一项大,偶数项都比前一项小,则称为一个摆动数列
**即a[2i]<a[2i-1],a[2i+1]>a[2i] ,数列可以只有一个数,该数为满足条件的任意值
**求长度为 m ,每个数都是 [1,n] 之间的正整数的摆动序列一共有多少个
**输入格式:输入一行包含两个整数 m,n
**输出格式:输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数
样例输入
3 4
样例输出
14
样例说明
以下是符合要求的摆动序列:
2 1 2
2 1 3
2 1 4
3 1 2
3 1 3
3 1 4
3 2 3
3 2 4
4 1 2
4 1 3
4 1 4
4 2 3
4 2 4
4 3 4
**数据规模:1 <= n,m <= 1000
**解题思路:DFS深度优先遍历,用栈来记录遍历的过程,每往下深一个层次就入栈,回溯则退栈,
**按序列的先后顺序入栈,将序列的第一个数入栈,然后进入下一层,然后再入栈进入下一层,循环
**直到序列长度达到要求则计数加1(即找到一个可行解)并回溯,若下一层次没有满足条件的结果则
**直接回溯,直到将所有可行解找到。
**第一层:序列长度为1;(1,2,3,...,n)
**第二层:序列长度为2;(<2,1>,<3,1>,<3,2>,...,<n,n-1>)
**第三层:序列长度为3:(<2,1,2>,<2,1,3>,<2,1,4>,...,<n,n-1,n>)
** ......
**第 n层:序列长度为n:(<2,1,2,1,...>,...,<n,n-1,n,n-1,...>)
**可看作是一个树状结构
*******************************************************************************/
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int m, n, sum; //m:数列长;n:数值上限;sum:可行数列计数
int stack[1004],top = 0; //栈,保存数列,入栈时DFS层次加深,退栈时回溯
void dfs(int t){
if(t == m){ //数列长度达到m时,计数加1,打印数列
sum++;
sum %= 10000;
// for(int k=0; k<m; k++){
// cout << stack[k] << " ";
// }
// cout << endl;
return;
}
//数列长度为0,(循环分支)为数列加入第一个数,(进入DFS下一层)开始在数列尾继续加数
if(t == 0){
for(int i = 1; i <= n; i++){
top = 0;
stack[top] = i; //入栈
dfs(1); //进入DFS下一层次
top--; //回溯
}
}
//数列的长度为偶数(即待添加数位于数列的奇数位)时
//(循环分支)为数列加入一个比数列尾大的数,(进入DFS下一层)开始在数列尾继续加数
if(t>0 && t%2 == 0){
for(int j = stack[top]+1; j <= n; j++){
top++;
stack[top] = j; //入栈
dfs(t+1); //进入DFS下一层次
top--; //回溯
}
}
//数列的长度为奇数(即待添加数位于数列的偶数位)时
//(循环分支)为数列加入一个比数列尾小的数,(进入DFS下一层)开始在数列尾继续加数
if(t%2 == 1){
for(int j = 1; j < stack[top]; j++){
top++;
stack[top] = j; //入栈
dfs(t+1); //进入DFS下一层次
top--; //回溯
}
}
}
int main(){
//int m, n, sum;
cin >> m >> n;
dfs(0); //执行DFS算法
cout << sum << endl;
return 0;
}
作者参考DFS算法想到的解题思路,写出程序,正确性无从考证,从思路上个人没发现什么漏洞,若有问题请留言,下面是测的两组数据:
输入3 4
输入4 4