数字三角形之动态规划法
题目描述
7
3 8
8 1 2
2 7 4 4
4 5 2 6 5
输入
输出
样例输入 Copy
<span style="background-color:#ffffff"><span style="color:#333333"><span style="color:#333333"><span style="background-color:#f5f5f5">2
1
1 2
3
1
1 2
1 2 3</span></span></span></span>
样例输出 Copy
<span style="background-color:#ffffff"><span style="color:#333333"><span style="color:#333333"><span style="background-color:#f5f5f5">3
6</span></span></span></span>
提示
a = [[0] * 100 for _ in range(100)]
dp = [[0] * 100 for _ in range(100)]
def solve(n, i, j):
if dp[i][j] != 0:
return dp[i][j]
else:
if i == n:
return a[i][j]
else:
dp[i][j] = a[i][j] + max(solve(n, i+1, j), solve(n, i+1, j+1))
return dp[i][j]
while True:
try:
n = int(input())
for i in range(1, n+1):
nums = list(map(int, input().split()))
for j in range(1, i+1):
dp[i][j] = 0
a[i][j] = nums[j-1]
print(solve(n, 1, 1))
except:
break
滚球游戏
题目描述
某滚球游戏规则如下:球从入口处(第一层)开始向下滚动,每次可向下滚动一层,直到滚至最下面一层为止。球每次可滚至左下、下方或右下三个方格中的任意一个,每个方格都有一个得分,如样例所示。第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
#include <stdio.h>
int max_da(int i, int j, int t) {
int a = (i > j) ? i : j;
int b = (j > t) ? j : t;
int c = (a > b) ? a : b;
return c;
}
int main() {
while (1) {
int n;
if (scanf("%d", &n) == EOF) {
break;
}
int a[101][201] = {0};
int p[101][201] = {0};
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= 2 * i - 1; j++) {
scanf("%d", &a[i][j]);
}
}
for (int j = 1; j <= 2 * n - 1; j++) {
p[n][j] = a[n][j];
}
for (int i = n - 1; i >= 1; i--) {
for (int j = 1; j <= 2 * i - 1; j++) {
p[i][j] = a[i][j] + max_da(p[i + 1][j], p[i + 1][j + 1], p[i + 1][j + 2]);
}
}
printf("%d\n", p[1][1]);
}
return 0;
}
最长公共子序列问题(LCS)之动态规划法
题目描述
使用动态规划算法求解两个序列的最长公共子序列的长度。
输入
每组输入包括两行,每行包括一个字符串。
输出
两个序列的最长公共子序列的长度。
样例输入 Copy
ACBCDABD ABDCABA
样例输出 Copy
5
#include <stdio.h>
#include <string.h>
int c[101][101];
int LSC(char x[], char y[], int m, int n) {
if (m == 0 || n == 0) {
return 0;
}
if (c[m][n] != 0) {
return c[m][n];
} else {
if (x[m - 1] == y[n - 1]) {
c[m][n] = LSC(x, y, m - 1, n - 1) + 1;
} else {
int left = LSC(x, y, m - 1, n);
int up = LSC(x, y, m, n - 1);
c[m][n] = (left > up) ? left : up;
}
return c[m][n];
}
}
int main() {
char x[101], y[101];
while (1) {
if (scanf("%s", x) == EOF) {
break;
}
scanf("%s", y);
int m = strlen(x);
int n = strlen(y);
memset(c, 0, sizeof(c));// 将二维数组 c 的所有元素初始化为0
printf("%d\n\n", LSC(x, y, m, n));
}
return 0;
}
斜线最大最小值
题目描述
求如图所示一个上三角矩阵中每一条斜线中的最大元素(L)和最小元素(S)。
输入
每组输入包括两部分,一部分为数字n,表示三角矩阵的行数。
第二部分即为三角矩阵。
输出
每一个对角线输出一行,每行包括Lx=Max, Sx=Min,其中x为斜线序号(序号从1开始),Max为该斜线上的最大值,Min为该斜线上的最小值。
样例输入 Copy
6 1 3 5 7 11 20 0 6 8 2 3 13 0 0 7 4 8 9 0 0 0 18 3 10 0 0 0 0 12 6 0 0 0 0 0 15
样例输出 Copy
L1=18, S1=1 L2=8, S2=3 L3=10, S3=2 L4=9, S4=3 L5=13, S5=11 L6=20, S6=20
def slove(n, a):
for r in range(n):
max = int(a[0][r])
min = int(a[0][r])
for i in range(0, n - r):
j = int(r + i)
if max < a[i][j]:
max = a[i][j]
if min > a[i][j]:
min = a[i][j]
print("L%d=%d, S%d=%d" % (r+1, max, r+1, min))
def in_data(n):
a = []
for i in range(n):
a.append(list(map(int, input().split())))
return a
while True:
n = int(input())
a = in_data(n)
slove(n, a)
矩阵连乘问题-动态规划求最优值
题目描述
使用动态规划算法求解矩阵连乘问题,输出最少乘法次数。
输入
每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。
输出
矩阵连乘最优计算次数。
样例输入 Copy
7 30 35 15 5 10 20 25
样例输出 Copy
15125
def slove(x, y):
for r in range(2, y):
for i in range(1, y-r+1):
j = i+r-1
dp[i][j] = dp[i+1][j]+p[i-1]*p[i]*p[j]
for k in range(i+1, j):
dp[i][j] = min(dp[i][j], dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j])
return dp[x][y-1]
while True:
n = int(input())
p = [int(i) for i in input().split()]
dp = [[0] * n for _ in range(n)]
print(slove(1, n))
矩阵连乘问题-构造最优解
题目描述
使用动态规划算法求解矩阵连乘问题。
输入
每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。
输出
矩阵连乘最优计算次序。
样例输入 Copy
7 30 35 15 5 10 20 25
样例输出 Copy
A[2:2] * A[3:3] A[1:1] * A[2:3] A[4:4] * A[5:5] A[4:5] * A[6:6] A[1:3] * A[4:6]
def slove(x, y):
for r in range(2, y):
for i in range(1, y-r+1):
j = i+r-1
dp[i][j] = dp[i+1][j]+p[i-1]*p[i]*p[j]
s[i][j] = i
for k in range(i+1, j):
t = dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j]
if t < dp[i][j]:
dp[i][j] = t
s[i][j] = k
def tr(i, j):
if i == j:
return
tr(i, s[i][j])
tr(s[i][j]+1, j)
m = s[i][j]+1
print(f"A[{i}:{s[i][j]}] * A[{m}:{j}]")
def in_data(n):
p = [int(i) for i in input().split()]
return p
while True:
n = int(input())
p = in_data(n)
dp = [[0] * n for _ in range(n)]
s = [[0] * n for _ in range(n)]
slove(1, n)
tr(1, n-1)