最大子段和
题目描述
给定n个整数(可能是负数)组成的序列a[1], a[2], a[3], …, a[n],求该序列的子段和如a[i]+a[i+1]+…+a[j]的最大值。
输入
每组输入包括两行,第一行为序列长度n,第二行为序列。
输出
输出字段和的最大值。
样例输入 Copy
5 -1 0 1 2 3
样例输出 Copy
6
while True:
n = int(input())
a = list(map(int, input().split()))
dp = [0] * n
MAX = a[0]
for i in range(1, n): # (1, n-1)
dp[i] = max(dp[i - 1] + a[i], a[i])
MAX = max(MAX, dp[i])
print(MAX)
#include <stdio.h>
int max(int a, int b) {
return a > b ? a : b;
}
int main() {
int a[1001];
int dp[1001];
int n;
while (~scanf("%d", &n)) {
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
dp[0] = a[0];
int MAX = dp[0];
for (int i = 1; i < n; i++) {
dp[i] = max(dp[i - 1] + a[i], a[i]);
MAX = max(MAX, dp[i]);
}
printf("%d\n", MAX);
}
return 0;
}
最大子段和升级版
题目描述
使用动态规划算法求整数数组(可能包含负整数)的最大子段和,以及和最大子段的起始位置和结束位置:
例如:输入数组(6,-1,5,4,-7),输出14, 1, 4,其中14表示最大子段和,1表示和最大的子段从第1个数字开始,4表示和最大的子段到第4个数字结束,即(6, -1 , 5, 4)。
输入
每组输入两行,第1行为数组中包含的整数个数n,第2行为n个整数(可能包含负整数),两两之间用空格隔开。
输出
输出最大子段和,以及和最大子段的起始位置和结束位置,两两之间用空格隔开。
样例输入 Copy
5 6 -1 5 4 -7
样例输出 Copy
14 1 4
#include <stdio.h>
int a[1001];
int dp[1001];
int max(int a, int b) {
return a > b ? a : b;
}
void solve(int a[], int n) {
int MAX, s, e;
s = 0;
e = 0;
dp[0] = a[0];
MAX = a[0];
for (int i = 1; i < n; i++) {
dp[i] = max(dp[i - 1] + a[i], a[i]);
if (dp[i] > MAX) {
MAX = dp[i];
e = i; //标记最后一个子段的结束下标
}
int max = MAX;
for (int i = e; i >= 0; i--) {
max = max - a[i];
if (max == 0) {
s = i; //标记最后一个子段的开始下标
break;
}
}
}
printf("%d %d %d\n", MAX, s + 1, e + 1);
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
solve(a, 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))
牛牛的字符串
题目描述
牛牛有两个字符串(可能包含空格),他想找出其中最长的公共连续子串的长度,希望你能帮助他。例如:两个字符串分别为"abede"和"abgde",结果为2。
输入
每组数据包括两行,每行为一个字符串。
输出
输出最长的公共连续子串的长度。
样例输入 Copy
abede abgde
样例输出 Copy
2
#include <stdio.h>
#include <string.h>
int c[100][100];
int lcs(char x[], char y[], int i, int j) {
for (int m = 1; m <= i; m++) {
for (int n = 1; n <= j; n++) {
if (x[m - 1] == y[n - 1]) {
c[m][n] = c[m - 1][n - 1] + 1;
} else {
c[m][n] = 0;
}
}
}
int max_val = c[0][0];
for (int p = 1; p <= i; p++) {
for (int q = 1; q <= j; q++) {
max_val = max_val < c[p][q] ? c[p][q] : max_val;
}
}
return max_val;
}
int main() {
char a[100], b[100];
scanf("%s", a);
scanf("%s", b);
int p = strlen(a);
int q = strlen(b);
int result = lcs(a, b, p, q);
printf("%d\n", result);
return 0;
}
最长公共子序列问题(LCS)-构造LCS
题目描述
使用动态规划算法求两个序列的最长公共子序列,需构造一条最长公共子序列。
输入
每组输入包括两行,每行包括一个字符串。
输出
两个字符序列的一条最长公共子序列。(输入已确保最长公共子序列的唯一性)
样例输入 Copy
acdbxx ccdxx
样例输出 Copy
cdxx
#include <stdio.h>
#include <string.h>
int c[100][100];
int b[100][100];
void lcslength(char x[], char y[], int i, int j) {
c[0][0] = 0;
b[0][0] = 0;
for (int m = 1; m <= i; m++) {
for (int n = 1; n <= j; n++) {
if (x[m - 1] == y[n - 1]) {
c[m][n] = c[m - 1][n - 1] + 1;
b[m][n] = 1;
} else if (c[m - 1][n] >= c[m][n - 1]) {
c[m][n] = c[m - 1][n];
b[m][n] = 2;
} else {
c[m][n] = c[m][n - 1];
b[m][n] = 3;
}
}
}
}
void lcs(int i, int j, char x[]) {
if (i == 0 || j == 0)
return;
if (b[i][j] == 1) {
lcs(i - 1, j - 1, x);
printf("%c", x[i - 1]);
} else if (b[i][j] == 2) {
lcs(i - 1, j, x);
} else {
lcs(i, j - 1, x);
}
}
int main() {
char a[100], b[100];
scanf("%s", a);
scanf("%s", b);
int p = strlen(a);
int q = strlen(b);
lcslength(a, b, p, q);
lcs(p, q, a);
return 0;
}
class Main:
def __init__(self):
self.c = [[0] * 100 for _ in range(100)]
self.b = [[0] * 100 for _ in range(100)]
def lcslength(self, x, y, i, j):
self.c[0][0] = 0
self.b[0][0] = 0
for m in range(1, i + 1):
for n in range(1, j + 1):
if x[m - 1] == y[n - 1]:
self.c[m][n] = self.c[m - 1][n - 1] + 1
self.b[m][n] = 1
elif self.c[m - 1][n] >= self.c[m][n - 1]:
self.c[m][n] = self.c[m - 1][n]
self.b[m][n] = 2
else:
self.c[m][n] = self.c[m][n - 1]
self.b[m][n] = 3
def lcs(self, i, j, x):
if i == 0 or j == 0:
return
if self.b[i][j] == 1:
self.lcs(i - 1, j - 1, x)
print(x[i - 1], end="")
elif self.b[i][j] == 2:
self.lcs(i - 1, j, x)
else:
self.lcs(i, j - 1, x)
if __name__ == "__main__":
a = input()
b = input()
c = Main()
p = len(a)
q = len(b)
c.lcslength(a, b, p, q)
c.lcs(p, q, list(a))