问题 A: 数字三角形之备忘录法
题目描述
7
3 8
8 1 2
2 7 4 4
4 5 2 6 5
输入
输出
样例输入 Copy
2 1 1 2 3 1 1 2 1 2 3
样例输出 Copy
3 6
提示
n = int(input())
while n:
a = []
for i in range(n):
a.append([int(x) for x in input().split()])
p = [[-1 for _ in range(105)] for _ in range(105)]
def max_sum(i, j):
if i == n - 1:
return a[i][j]
if p[i][j] != -1:
return p[i][j]
p[i][j] = a[i][j] + max(max_sum(i + 1, j), max_sum(i + 1, j + 1))
return p[i][j]
result = max_sum(0, 0)
print(result)
n = int(input())
问题 B: 数字三角形之动态规划法
题目描述
7
3 8
8 1 2
2 7 4 4
4 5 2 6 5
输入
输出
样例输入 Copy
2 1 1 2 3 1 1 2 1 2 3
样例输出 Copy
3 6
提示
n = int(input())
while n:
a = []
for i in range(n):
a.append([int(x) for x in input().split()])
p = [[-1 for _ in range(105)] for _ in range(105)]
for i in range(n - 1, -1, -1):
for j in range(0, i + 1):
if i == n - 1:
p[i][j] = a[i][j]
else:
p[i][j] = a[i][j] + max(p[i + 1][j], p[i + 1][j + 1])
print(p[0][0])
n = int(input())
问题 C: HNUCM的路径统计
题目描述
HNUCM的小明同学特别喜欢下围棋。
一天他盯着围棋棋盘,想到这么一个问题:
有一个矩形棋盘,该棋盘跟围棋棋盘相似,由一个个正方形的小方格组成,小方格一共有n行,每行有m个小方格。如果将一个棋子放在左上角第1行第1列的格子中,每次走一步,但是每步只能朝右或者朝下走一格。
请问从左上角的方格(即第1行第1列)走到右下角(即第n行第m列)的方格,一共有多少条不同的路径?
输入
单组输入。
输入两个正整数n和m,分别表示棋盘的行数和列数,n和m均不超过100,两者之间用1个英文空格隔开。
输出
输出从左上角到右下角满足条件的不同路径数量。答案对1e9+7取模
样例输入 Copy
2 3
样例输出 Copy
3
def unique_paths(n, m):
MOD = 10 ** 9 + 7
dp = [[0] * (m + 1) for _ in range(n + 1)]
# 初始化边界条件
for i in range(1, n + 1):
dp[i][1] = 1
for j in range(1, m + 1):
dp[1][j] = 1
# 动态规划计算路径数量
for i in range(2, n + 1):
for j in range(2, m + 1):
dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]) % MOD
return dp[n][m]
# 输入处理
n, m = map(int, input().split())
print(unique_paths(n, m))
问题 D: 滚球游戏
题目描述
某滚球游戏规则如下:球从入口处(第一层)开始向下滚动,每次可向下滚动一层,直到滚至最下面一层为止。球每次可滚至左下、下方或右下三个方格中的任意一个,每个方格都有一个得分,如样例所示。第1层有1个方格,第2层有3个方格,……,以此类推,第n层有2*n-1个方格。设计一个算法,使得球从入口滚至最下面一层的总得分和最大。
输入
对于每个样例,第1行的正整数n表示数字三角形的行数。(n<=100)
接下来n行包含一个数字三角形,每一行包含2*n-1个方格,对应有2*n-1个表示得分的正整数(不超过10^5),每两个数字之间用空格隔开。
每两组样例之间有一个空行。
输出
球从入口(第一层)滚至最下面一层的最大得分和。
样例输入 Copy
2 3 2 1 3 3 1 2 1 2 3 4 2 1 3
样例输出 Copy
6 7
def maxScore(n, arr):
dp = [[0] * (2 * n - 1) for _ in range(n)]
for i in range(n):
for j in range(2 * i + 1):
if i == 0:
dp[i][j] = arr[i][j]
else:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1], dp[i - 1][j - 2]) + arr[i][j]
return max(dp[-1])
inputs = []
while True:
n = input()
if len(n) == 0:
continue
n = int(n)
arr = []
for i in range(n):
arr.append(list(map(int, input().split())))
inputs.append((n, arr))
result = maxScore(n, arr)
print(result)
问题 E: X星金币问题
题目描述
小X在挑战一个收集金币的游戏。
已知有一个由若干小方格组成的矩形区域,一共包含M行和N列。每一个小方格中都有一个正整数,表示该方格中的金币数目。
现在小X从最上面的行(第1行)任选一个方格作为出发点,每一次只能向正下方、左下方或者右下方走一格,但不能走出矩形区域,最终要到达矩形区域的最后一行。
小X每走一格就会收集该方格中的全部金币。
请你编写一个程序,输出小X最多可以收集多少枚金币?(包含起始方格和结束方格中所包含的金币)。
输入
单组输入。
第1行输入两个正整数M和N,分别表示矩形区域的行和列,M和N均不超过1000,两者之间用一个英文空格隔开。
接下来M行,每行包含N个正整数,每个正整数表示对应方格中的金币数,每个方格中的金币数均不超过100。同一行的两个正整数之间用一个英文空格隔开。
输出
输出一个正整数,表示小X从第1行到最后一行能够收集到的最多金币数。
样例输入 Copy
3 3 2 1 1 8 5 9 2 1 10
样例输出 Copy
20
def max_score_function(n, m):
arr = []
dp = [[0] * m for i in range(n)]
# 读取矩阵的元素
for i in range(n):
row = list(map(int, input().split()))
arr.append(row)
# 初始化动态规划数组
for i in range(n):
for j in range(m):
if i == 0:
dp[i][j] = arr[i][j]
else:
# 检查是否超出右侧边界
if j + 1 < m:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1], dp[i - 1][j + 1]) + arr[i][j]
else:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]) + arr[i][j]
# 返回最后一行的最大得分
return max(dp[-1])
while True:
try:
# 读取矩阵的维度
n, m = map(int, input().split())
# 检查是否为0,表示没有更多输入
if n == 0 and m == 0:
break
# 计算最大得分并打印
max_score = max_score_function(n, m)
print(max_score)
except EOFError:
break
n, m = map(int, input().split())
max_score = max_score_function(n, m)
print("Max score:", max_score)
问题 F: XP的矩阵
题目描述
XP学长觉得矩阵很美,虽然他也不知道美在哪里,因此,他决定挖掘一下矩阵的美。现在给定一个m行n列的矩阵,从左上角开始每次只能向右或者向下移动,最后到达右下角的位置,将路径上的所有数字累加起来作为这条路径的路径和。XP学长决定编写一个程序来求所有路径和中的最小路径和。例如,下面矩阵中的路径1-3-1-0-6-1-0是所有路径中路径和最小的,返回结果是12。
1 3 5 9
8 1 3 4
5 0 6 1
8 8 4 0
输入
输入包含多组测试用例,第一行输入一个T表示测试数据组数,(1<=T<=15)
接下来有T组数据,每组先输入两个整数M,N接下来输入M*N的矩阵(1<=N,M<=1000),且最终结果在int范围内。
输出
输出路径和的最小值。
样例输入 Copy
1 4 4 1 3 5 9 8 1 3 4 5 0 6 1 8 8 4 0
样例输出 Copy
12
def calculate_min_path_sum(n, m, matrix):
a = [[0] * (m + 1) for _ in range(n + 1)]
dp = [[0] * (m + 1) for _ in range(n + 1)]
# 将矩阵元素填充到a数组中
for i in range(1, n + 1):
for j in range(1, m + 1):
a[i][j] = matrix[i - 1][j - 1]
# 初始化边界条件
if j == 1:
dp[i][j] = dp[i - 1][j] + a[i][j]
if i == 1:
dp[i][j] = dp[i][j - 1] + a[i][j]
# 动态规划计算最小路径和
for i in range(2, n + 1):
for j in range(2, m + 1):
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + a[i][j]
# 返回最小路径和
return dp[n][m]
while True:
t = int(input())
if t == 0: # 假设输入0表示没有更多测试用例
break
for _ in range(t):
n, m = map(int, input().split())
matrix = []
# 读取矩阵的每一行
for _ in range(n):
row = list(map(int, input().split()))
matrix.append(row)
# 计算并打印最小路径和
min_path_sum = calculate_min_path_sum(n, m, matrix)
print(min_path_sum)