2023年秋季学期《算法分析与设计》练习10 OJ-1402 算法分析与设计练习10,使用python、C语言

最大子段和

题目描述

给定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))

  • 11
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值