📅  最后修改于: 2023-12-03 14:50:47.797000             🧑  作者: Mango
这是ISRO(国际空间研究组织)的2017年计算机科学考试中的问题45。
给定两个整数 n
和 k
,你需要求出所有可能的由 1
到 n
组成的数字排列,使得相邻两个数字的差的绝对值不超过 k
。
输入文件包含两个整数 n
和 k
。
输出文件包含一个整数,表示满足要求的排列数量,由于答案可能很大,因此需要输出对 10^9+7
取模的结果。
4 1
85
本题可以使用动态规划的方法进行求解。
定义 dp[i][j][0/1]
为有 i
个数字,最后一个数字是 j
,最后两个数字的差的绝对值是否不超过 k
。其中 0
表示超过,1
表示没有超过。根据这个定义,可以得到如下递推式:
dp[i][j][0] = dp[i-1][j-1][1] + dp[i-1][j-2][1] + ... + dp[i-1][j-k][1]
dp[i][j][1] = ∑dp[i-1][j'][0/1] (j - k <= j' <= j + k && j' != j)
其中第一个递推式表示当最后一个数字为 j
且最后两个数字的差的绝对值超过了 k
时,可以从所有合法的 j'
转移过来。第二个递推式表示当最后一个数字为 j
且最后两个数字的差的绝对值不超过 k
时,可以从所有合法的 j'
和 dp[i-1][j'][0/1]
转移过来。
根据递推式,本题的动态规划算法需要使用两个循环枚举 i
和 j
,时间复杂度为 O(n^2k)
。即可得到答案 dp[n][1~n][0/1]
的和。
MOD = 10**9 + 7
n, k = map(int, input().split())
dp = [[[0, 0] for j in range(n+1)] for i in range(n+1)]
for i in range(1, n+1):
dp[1][i][0] = i-1
dp[1][i][1] = n-i
for i in range(2, n+1):
for j in range(1, n+1):
for x in range(1, k+1):
if j-x >= 1:
dp[i][j][0] = (dp[i][j][0] + dp[i-1][j-x][1]) % MOD
if j+x <= n:
dp[i][j][0] = (dp[i][j][0] + dp[i-1][j+x][1]) % MOD
for j2 in range(1, n+1):
if abs(j-j2) <= k and j != j2:
dp[i][j][1] = (dp[i][j][1] + dp[i-1][j2][0] + dp[i-1][j2][1]) % MOD
ans = 0
for i in range(1, n+1):
ans = (ans + dp[n][i][0] + dp[n][i][1]) % MOD
print(ans)
代码片段按markdown标明