题目描述
如果一个序列的奇数项都比前一项大,偶数项都比前一项小,则称为一个摆动序列。即 a 2 i < a 2 i − 1 , a 2 i + 1 > a 2 i a_{2i} < a_{2i-1}, a_{2i+1}\ > a_{2i} a2i<a2i−1,a2i+1 >a2i
小明想知道,长度为 m,每个数都是 1 到 n 之间的正整数的摆动序列一共有多少个。
输入描述
输入一行包含两个整数 m,n(1≤n,m≤1000)。
输出描述
输出一个整数,表示答案。答案可能很大,请输出答案除以 10000 的余数。
输入输出样例
示例
输入
3 4
输出
14
动态规划模板
动态规划模板——Python版本这篇博客写的不错。
dp = [] * (n-1) # 1.dp数组初始化
dp[x] = [] # 2.特殊值赋值
for i in range(): # 3.循环遍历
for j in range():
dp[j] = min(dp[j], dp[i]+ abc[i, j]) # 4.递推公式
print(dp[-1]) # 5. 输出
解法
下面的方法是一样的,一个没解析,一个有解析。
m, n = map(int,input().split())
res = m if m > n else n # 动态生成二维数组
dp = [[0 for i in range(res + 2)] for j in range(res + 2)]
for i in range(1, n+ 1): # 初始化为下一行i可以选择的值的数目
dp[1][i]=n-i+1 # 比如dp11 = 4,即是第一行可选4个
for i in range(2, m + 1):
if i % 2 == 1:
for j in range(n, 0, -1):
dp[i][j]= (dp[i-1][j-1]+dp[i][j+1])%10000
else:
for j in range(1, n + 1):
dp[i][j]=dp[i-1][j+1]+dp[i][j-1]% 10000
ans = dp[m][1] if m % 2 == 1 else dp[m][n]
print(ans)
m, n = map(int,input().split())
res = m if m > n else n # 动态生成二维数组
dp = [[0 for i in range(res + 2)] for j in range(res + 2)]
for i in range(1, n+ 1): # 初始化为下一行i可以选择的值的数目
dp[1][i]=n-i+1 # 比如dp11 = 4,即是第一行可选4个
# =============================================================================
# 注意 !!!!!!!!
# 第几行代表序列中填的第几个数
# 在奇数行中,dp[i][j]含义为:第i个数选择大于等于j的数时的方案总数。
# 在偶数行中,dp[i][j]含义为:第i个数选择小于等于j的数时的方案总数。
# 注意奇偶 奇偶 奇偶
# ============================================================================
for i in range(2, m + 1):
if i % 2 == 1:
# 奇数行,第i个数填大于等于j有多少种情况
# 因为大于等于j的情况=等于j的情况 + 大于等于j+1的情况,
# 而大于等于j+1的情况=等于j的情况 + 大于等于j+2的情况
# 一直递推累加下去,这里我们从j取最大值开始,采用 倒序 动态记忆化叠加
for j in range(n, 0, -1):
dp[i][j]= (dp[i-1][j-1]+dp[i][j+1])%10000# 不要忘了题目方案总数大于10000后要取余
# 第一轮理解,这一i奇数行 选择大于等于j的方案数 (这时j=n 第一轮)
# = 上一行i-1偶数行中选择小于j(即小于等于j-1)的方案 与 最末尾最大的数j组合的方案数(即 dp[i-1][j-1]) + dp[i][j+1] (此时dp[i][j+1]=0 ,因为j=n,j+1不在1~n范围,所以为零)
# 第二轮理解,这一i奇数行选择大于等于j的方案数 (这时j=n-- 第二轮)
# = 上一行i-1偶数行中选择小于等于j(即小于等于j-1)的方案 与j组合的方案数 (即 dp[i-1][j-1]) 加上 dp[i][j+1] (即 上一轮中这一奇数行j选择大于等于n的方案数)
# 以此类推
else:
# 偶数行 ,第i个数填小于等于j有多少种情况
# 因为小于等于j的情况=等于j的情况 + 小于等于j-1的情况,
# 而小于等于j-1的情况=等于j的情况 + 小于等于j-2的情况
# 一直递推累加下去,这里我们从j取最小值开始,采用 正序 动态记忆化叠加一下
for j in range(1, n + 1):
dp[i][j]=dp[i-1][j+1]+dp[i][j-1]%10000
# 如果m长度为奇数,选择dp[m][1], 如果m长度为偶数,选择dp[m][n]
ans = dp[m][1] if m % 2 == 1 else dp[m][n]
print(ans)