2020蓝桥杯A组模拟试题二第8题摆动序列(自写)

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
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值