2023年秋季学期《算法分析与设计》练习11 OJ-1405 算法分析与设计练习11,使用python

出列人数

题目描述

有N位同学站在一排,体育老师要请其中的(N-K)位同学出列,将剩下的K位同学从左到右依次编号为1,2,3,…K,他们的身高分别为T1,T2,T3,…TK,要求满足T1<T2<T3<…<TK。已知N位同学的身高,请设计一个算法,计算最少需要几位同学出列可使得剩下的同学满足上述要求。

输入

多组输入,对于每一组测试数据,第1行N表示同学数量(n<=1000)。
第2行包含N个正整数,分别表示每一个同学的身高。(单位:厘米)

输出

输出最少需要出列的同学人数。

样例输入 Copy
4
172 185 169 178
5
165 168 174 170 182
样例输出 Copy
2
1
def solve(a, b, n):
    b[0] = 1
    max_val = b[0]
    for i in range(1, n):   # (1,n-1)
        max_len = 0
        for j in range(i - 1, -1, -1):      # (0,i-1)
            if a[i] > a[j] and b[j] > max_len:      # 非递减,并且b[]记录最大长度,跳过小于前面一个元素的元素,不加一
                max_len = b[j]
        b[i] = max_len + 1
        if b[i] > max_val:
            max_val = b[i]
    return max_val

while True:
    n = int(input())
    a = list(map(int, input().split()))
    b = [0] * (n + 1)
    result = solve(a, b, n)
    count = n - result
    print(count)

0-1背包问题

题目描述

给定n种物品和一个背包,物品i的重量是Wi,其价值为Vi,背包的容量为C。如何选择装入背包的物品,可以使得装入背包中物品的总价值最大?

输入

每组输入包括三行,
第一行包括物品个数n,以及背包容量C。
第二、三行包括两个一维数组,分别为每一种物品的价值和重量。

输出

输出包括两行,第一行为背包的最大总价值,第二行为所选取的物品。
例如:最大总价值=15,物品选取策略为11001。数据保证答案唯一。

样例输入 Copy
5 10
6 3 5 4 6
2 2 6 5 4
样例输出 Copy
15
11001
while True:
    n, c = map(int, input().split())
    v = list(map(int, input().split()))
    w = list(map(int, input().split()))
    x = ['0'] * n
    # 剩余容量j=(0,c)  物品个数i=(0,n-1)
    dp = [[0] * (c + 1) for _ in range(n)]
    for i in range(n):   # (0,n-1)
        for j in range(c + 1):
            if w[i] > j:
                dp[i][j] = dp[i - 1][j]
            else:
                dp[i][j] = max(dp[i - 1][j - w[i]] + v[i], dp[i - 1][j])
    print(dp[n - 1][c])
    y = c
    for i in range(n - 1, -1, -1):  # (0,n-1)
        if dp[i][y] != dp[i - 1][y]:
            x[i] = '1'  # list包含数字,不能直接转化成字符串
            y = y - w[i]
    print("".join(x))

XP的午餐

题目描述

XP每天都会思考一个问题,今天午餐去哪里吃?这是一个很重要的问题,这会影响到他下午的体力值。他的午餐预算是M元,现在有N种菜品,每一种菜品的价格和能够提供的体力值已知(每种菜品只能选择一次),请问如何选择菜品能够让XP下午的体力值最大呢?

输入

多组输入
第一行:M元和菜品数量N。
接下来N行,每一行两个整数,分别表示每一种菜品的价格(vi)和能够获得的体力值(wi)。
(0<N<=20,0<=M<=1000)(0<=vi<=50,0<=wi<=100)

输出

最大体力值。

样例输入 Copy
10 5
1 5
2 4
3 3
4 2
5 1
样例输出 Copy
14
while True:
    m, n = map(int, input().split())
    v = []
    w = []
    for i in range(n):
        temp = list(map(int, input().split()))
        v.append(temp[0])
        w.append(temp[1])
    # 剩余预算j=(0,m)  菜品个数i=(0,n-1)
    dp = [[0] * (m + 1) for _ in range(n)]
    for i in range(n):   # (0,n-1)
        for j in range(m + 1):
            if v[i] > j:
                dp[i][j] = dp[i - 1][j]
            else:
                dp[i][j] = max(dp[i - 1][j - v[i]] + w[i], dp[i - 1][j])
    print(dp[n - 1][m])

补充能量

题目描述

一年一度的宇宙超级运动会在宇宙奥特英雄体育场隆重举行。X星人为这场运动会准备了很长时间,他大显身手的时刻终于到了!
为了保持良好的竞技状态和充沛的体能,X星人准备了N个不同的能量包,每个能量包都有一个重量值和能量值。由于这些能量包的特殊性,必须要完整地使用一个能量包才能够发挥功效,否则将失去能量值。
考虑到竞赛的公平性,竞赛组委会规定每个人赛前补充的能量包的总重量不能超过W。
现在需要你编写一个程序计算出X星人能够拥有的最大能量值是多少?

输入

单组输入。
第1行包含两个正整数N和W,其中N<=103,W<=103。
第2行包含N个正整数,分别表示每一个能量包的重量,两两之间用空格隔开。
第3行包含N个正整数,分别表示每一个能量包的能量值,两两之间用空格隔开。

输出

输出X星人能够拥有的最大能量值。

样例输入 Copy
3 10
4 5 7
100 120 200
样例输出 Copy
220
while True:
    n, c = map(int, input().split())
    w = list(map(int, input().split()))
    v = list(map(int, input().split()))
    # 剩余容量j=(0,c)  物品个数i=(0,n-1)
    dp = [[0] * (c + 1) for _ in range(n)]
    for i in range(n):   # (0,n-1)
        for j in range(c + 1):
            if w[i] > j:
                dp[i][j] = dp[i - 1][j]
            else:
                dp[i][j] = max(dp[i - 1][j - w[i]] + v[i], dp[i - 1][j])
    print(dp[n - 1][c])

最少硬币

题目描述

假设有4种硬币,它们的面值分别为1分、5分、10分和25分。
现在要找给顾客n分钱。
请问怎样找零钱才能使给顾客的硬币个数最少?
输出所需最少硬币的枚数。

输入

输入需要找给顾客的零钱n(单位:分)。

输出

输出所需最少硬币的枚数。

样例输入 Copy
8
10
63
样例输出 Copy
4
1
6
# 动态规划算法
coins = [1, 5, 10, 25]
while True:
    n = int(input())
    min_count = 0
    dp = [0] * (n + 1)
    for i in range(4):  # (0, 3)
        for j in range(coins[i], n + 1):    # (coins[i],n)
            if dp[j] != 0:
                dp[j] = min(dp[j - coins[i]] + 1, dp[j])
            else:
                dp[j] = dp[j - coins[i]] + 1
    print(dp[n])

# 贪心算法
# def min_num(money):
#     num = 0
#     for i in [25,10, 5, 1]:
#         num += int(money/i)
#         money = money%i
#     return num
#
# while True:
#         n=int(input())
#         print(min_num(n))

图书排序

题目描述

某图书销售管理系统需要对图书(Book)进行排序,每一本图书包含书名(bookName)、销量(bookSales)、价格(bookPrice)等属性,要求先按照销量由大到小排序,对于销量相同的图书再按照价格由小到大排序。

输入

每组输入包括两个部分,第一部分为书的数量n,
接下来n行则为n本书的信息。 按顺序输入书名(不超过20个字)、销量、价格。

输出

输出排序后的信息,每个属性用空格隔开

样例输入 Copy
7
C++程序设计 120 25.00
软件工程 96 48.00
高等数学 80 32.50
算法分析与设计 96 54.00
离散数学 96 28.00
计算机网络 96 36.00
操作系统 115 45.00
样例输出 Copy
C++程序设计 120 25.00
操作系统 115 45.00
离散数学 96 28.00
计算机网络 96 36.00
软件工程 96 48.00
算法分析与设计 96 54.00
高等数学 80 32.50
while True:
    n, p = map(int, input().split())
    nums, prices, values = [], [], []
    dp = [0] * (p + 1)
    for i in range(n):
        x, y, z = map(int, input().split())
        nums.append(x), prices.append(y), values.append(z)
    for index, price in enumerate(prices):
        for j in range(p, price - 1, -1):
            for k in range(min(nums[index], j // price) + 1):
                dp[j] = max(dp[j], dp[j - k * price] + k * values[index])
    print(dp[p])

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一道经典的位运算题目,考察对二进制的理解和位运算的熟练程度。 题目描述: 给定一个长度为 $n$ 的数组 $a$,初始时每个数的值都为 $0$。现在有 $m$ 个操作,每个操作为一次询问或修改。 对于询问,给出两个整数 $l,r$, $a_l \oplus a_{l+1} \oplus \cdots \oplus a_r$ 的值。 对于修改,给出一个整数 $x$,表示将 $a_x$ 的值加 $1$。 输入格式: 第一行两个整数 $n,m$。 接下来 $m$ 行,每行描述一次操作,格式如下: 1 l r:表示询问区间 $[l,r]$ 的异或和。 2 x:表示将 $a_x$ 的值加 $1$。 输出格式: 对于每个询问操作,输出一个整数表示答案,每个答案占一行。 数据范围: $1 \leq n,m \leq 10^5$,$0 \leq a_i \leq 2^{30}$,$1 \leq l \leq r \leq n$,$1 \leq x \leq n$ 输入样例: 5 5 2 1 2 3 1 2 4 2 2 1 1 5 输出样例: 0 2 解题思路: 对于询问操作,可以利用异或的性质,即 $a \oplus b \oplus a = b$,将 $a_l \oplus a_{l+1} \oplus \cdots \oplus a_r$ 转化为 $(a_1 \oplus \cdots \oplus a_{l-1}) \oplus (a_1 \oplus \cdots \oplus a_r)$,因为两个前缀异或后的结果可以相互抵消,最后的结果即为 $a_1 \oplus \cdots \oplus a_{l-1} \oplus a_1 \oplus \cdots \oplus a_r = a_l \oplus \cdots \oplus a_r$。 对于修改操作,可以将 $a_x$ 对应的二进制数的每一位都分离出来,然后对应位置进行修改即可。由于只有加 $1$ 操作,所以只需将最后一位加 $1$ 即可,其余位不变。 参考代码:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值