算法设计与分析(5题Python版)

news2024/10/6 0:37:15

1、阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有N堆金币,第i堆金币的总重量和总价值分别是m,v。阿里巴巴有一个承重量为T的背包,但并不一定有办法将全部的金币都装进去。
他想装走尽可能多价值的金币,所有金币都可以随意分割,分割完的金币重量价值比(也就是单位价格)不变。请问阿里巴巴最多可以拿走多少价值的金币?
(1)请给出存储已知数据的数据结构〈2分)
(2)请给出你选择的算法策略(2分)
(3)请写出算法步骤〈任选一种自然语言·伪代码﹑程序进行描逑〉(6分)
(4)假设背包里有4个物品,请自行设计一个算法,并给出输出结果〈物品的重量﹑价值、背包容量自拟)

例题分析:

根据题意可以知道这是一个分数背包问题(金币重量价值比可知)。就是说在背包容量一定的情况下,每个物品可以选择放入部分或全部,要求放入背包中的物品的总价值最大化或者总重量最小化。(01背包不可以使用贪心策略,但是分数背包却是不二之选)

那么,这一题求的是在背包为T的情况下,能拿走最多的金币是多少。

数据结构:我们可以使用列表嵌套映射来存储每堆金币的重量和价值。

coins = [
    {"w": m1, "v": v1},
    {"w": m2, "v": v2},
    ...
    {"w": mN, "v": vN}
]

算法策略计算每堆金币的单位价值,即价值/重量。按单位价值(v/w)从高到低对金币堆进行排序。从单位价值最高的金币堆开始,尽可能多地装入背包,直到背包装满或没有金币可装。(贪心策略,只考虑目前的最好选择)

代码实现

class Item:
    def __init__(self, weight, value):
        self.weight = weight
        self.value = value
        self.value_per_weight = value / weight

def fractional_knapsack(coins, T):
    coins.sort(key=lambda x: x.value_per_weight, reverse=True)
    total_value = 0
    remaining_capacity = T
    for item in coins:
        if remaining_capacity == 0:
            break
        if remaining_capacity >= item.weight:
            total_value += item.value
            remaining_capacity -= item.weight
        else:
            total_value += item.value_per_weight * remaining_capacity
            break
    return total_value

if __name__ == "__main__":
    n, T = map(int, input().split())
    values = list(map(int, input().split()))
    weights = list(map(int, input().split()))
    # python内部的列表生成式
    coins = [Item(weights[i], values[i]) for i in range(n)]
    max_value = fractional_knapsack(coins, T)
    print(f"{max_value:.1f}")
输入:
4 20 
25 24 15 10
18 15 10 4
输出:
35.5
2、游艇俱乐部在长红上设置了n个游艇出租站,游客可以在上游的出租站租用游艇,在下游的任何一个游艇出租站归还游艇。游艇出租站i到出租站j(i<j)之间的租金为r(i,j)。求解从游艇出租站1到游艇出租站n所需的最少的租金?
(1〉写出选用的算法策略(2分)
(2)写出该算法策略的思想(4分)
(3)写出求解问题所用的数据结构(2分)
(4)写出求解问题的算法步骤(5分)
(5)分析算法的时间复杂度和空间复杂度(2分)

例题分析:

n个出租站,游艇i到j的租金为r(i,j),求从1到n所需的最少租金。

租金直接使用二维数组表示(r[i][j])。

那么,我们就可以想到是不是可以用 dp[j] 表示从1到j的最少租金,故所求结果为 dp[n]。

(1)动态规划。

(2)dp[j]=min(dp[j],dp[i]+r[i][j]) (i>j)

(3)列表

(4)初始化dp数组dp[1]=0,其余的dp[i]全部为inf,遍历每一个出租站i,对于每个i再遍历后边的出租站j,更新dp[j]。

(5)时间复杂度:o(n2)空间复杂度:o(n2)

def min_rent(n, r):
    # float('inf') 正无穷大  float('-inf')
    dp = [float('inf')] * (n + 1)
    dp[1] = 0
    for i in range(1, n):
        for j in range(i + 1, n + 1):
            dp[j] = min(dp[j], dp[i] + r[i][j])
    return dp[n]

n = int(input())
r = [[0] * (n + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
    values = list(map(int, input().split()))
    for j in range(i + 1, n + 1):
        r[i][j] = values[j - i - 1]
        r[j][i] = r[i][j]

result = min_rent(n, r)
print(result)
3、三个矩阵大小分别为3*4·4*5·5*6,求其相乘的最优结合次序?
(1)写出所用的求解方法(4分)
(2)描述该方法求解的步骤(4分)
(3)给出求解过程(4分)
(4)给出求解结果(2分)

例题分析:

(1) 求解方法:动态规划

(2) 求解步骤:
   1. 创建一个二维数组 `dp`,其中 `dp[i][j]` 表示从第 `i` 个矩阵到第 `j` 个矩阵相乘所需的最小计算次数。
   2. 初始化 `dp`,将对角线上的元素设为 0,表示单个矩阵相乘的次数为 0。
   3. 使用两重循环遍历所有可能的长度 `len`(从 2 开始到矩阵总数),在每个长度下再使用一个循环遍历所有起始位置 `i`,计算相应的结束位置 `j`。
   4. 对于每个位置 `(i, j)`,遍历中间位置 `k`(从 `i` 到 `j-1`),更新 `dp[i][j]` 的值为 `dp[i][k] + dp[k+1][j] + matrix[i].row * matrix[k].col * matrix[j].col` 的最小值,其中 `matrix[i].row` 表示第 `i` 个矩阵的行数,`matrix[k].col` 表示第 `k` 个矩阵的列数,`matrix[j].col` 表示第 `j` 个矩阵的列数。
   5. 最终 `dp[0][n-1]` 中存储的值即为所有矩阵相乘的最小计算次数。

(3) 求解过程:

def matrix_chain_order(p):
    n = len(p) - 1
    m = [[0 for _ in range(n)] for _ in range(n)]
    s = [[0 for _ in range(n)] for _ in range(n)]
    for l in range(2, n):
        for i in range(n - l + 1):
            j = i + l - 1
            m[i][j] = float('inf')
            for k in range(i, j):
                q = m[i][k] + m[k + 1][j] + p[i] * p[k + 1] * p[j + 1]
                if q < m[i][j]:
                    m[i][j] = q
                    s[i][j] = k
    return s
def print_optimal_parens(s, i, j):
    if i == j:
        print(f"A{i}", end="")
    else:
        print("(", end="")
        print_optimal_parens(s, i, s[i][j])
        print_optimal_parens(s, s[i][j] + 1, j)
        print(")", end="")
def main():
    p = [3, 4, 5, 6]
    s = matrix_chain_order(p)
    print_optimal_parens(s, 0, len(p) - 2)
    print()
if __name__ == "__main__":
    main()
4、输入一个无重复字符的字符串s,打印出该字符串中字符的所有排列,请使用回溯法求解该问题。
(1)请定义问题的解空间。(2分)
〔2)写出解空间的组织结构。〔1分)
(3)写出约束条件和限界条件。(2分)
(4)写出该问题的算法步骤。(6分)
〔5)给定‘abc’,请给出算法求解的结果。〔2分)

例题分析:

(1) 解空间:所有无重复字符的字符串的排列。

(2) 解空间的组织结构:使用一个数组 `visited` 记录每个字符是否被访问过,使用一个字符串 `path` 记录当前路径上的字符排列。

(3) 约束条件和限界条件:
   - 约束条件:每个字符只能被使用一次,保证排列的唯一性。
   - 限界条件:当当前路径上的字符数等于输入字符串的长度时,表示已经得到一个完整的排列。

(4) 算法步骤:
   1. 初始化一个长度为字符串长度的 `visited` 数组,全部初始化为 `false`,表示所有字符均未被访问过。
   2. 初始化一个空的字符串 `path`,用于记录当前路径上的字符排列。
   3. 从第一个字符开始,调用回溯函数,遍历所有可能的排列。
   4. 回溯函数的参数包括当前路径 `path`、访问状态数组 `visited`、输入字符串 `s`,以及结果集合 `res`。
   5. 在回溯函数中,遍历字符串 `s` 的每个字符,如果该字符未被访问过,则将其加入到 `path` 中,并将 `visited` 对应位置设为 `true`,然后递归调用回溯函数。
   6. 当 `path` 的长度等于 `s` 的长度时,表示已经得到一个排列,将 `path` 加入到结果集合 `res` 中。
   7. 回溯结束后,返回结果集合 `res`。

(5) 算法求解结果:
 

def backtrack(path, visited, s, res):
    if len(path) == len(s):
        res.append(path)
        return
    for i in range(len(s)):
        if not visited[i]:
            visited[i] = True
            backtrack(path + s[i], visited, s, res)
            visited[i] = False

def permutation(s):
    res = []
    visited = [False] * len(s)
    backtrack("", visited, s, res)
    return res

s = "abc"
result = permutation(s)
for perm in result:
    print(perm)
5、最优装载问题:有n个物品,第i个物品的重量为wi。在不超过最大承载量的范围内,你要选择尽可能多的物品。请问你最多可以选择多少件物品?
(1〉你有几种方法求解该问题,请写出方法名称。(要求至少写出2种)(4分)
(2〉请从你的解决方法中,选择1种方法,设计具体求解步骤。(6分)
(3〉根据你的求解步骤,使用给定的输入样例,写出每个步骤的处理结果。(4分)

例题分析:

可以使用数组存储每一个物品的重量,然后从小到大给数组排个序,循环小于最大承载量,可以累加判断也可以相减判断。

(1)贪心策略、动态规划

(2)贪心策略:每次选择当前最优解。将物品按照重量从小到大排序。从最轻的物品开始依次尝试装载,直到超过最大承载量为止。返回装载的物品数量。

(3)代码:

def load_problem(weights, c):
    weights.sort()
    tsum = 0.0
    temp = 0
    for weight in weights:
        tsum += weight
        if tsum <= c:
            temp += 1
        else:
            break
    return temp

def main():
    c, num = map(float, input().split())
    weights = list(map(float, input().split()))

    result = load_problem(weights, c)
    print(result)

if __name__ == "__main__":
    main()
输入:
10 3
1 3 13
输出:
2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1809725.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

攻防世界---misc---Excaliflag

1、题目描述&#xff0c;下载附件是一张图片 2、用winhex分析&#xff0c;没有发现奇怪的地方 3、在kali中使用binwalk -e 命令&#xff0c;虽然分离出来了一些东西&#xff0c;但是不是有用的 4、最后用stegsolve分析&#xff0c;切换图片&#xff0c;发现有字符串&#xff0c…

tcp协议中机制的总结

目录 总结 分析 三次握手 总结 分析 其中,序列号不止用来排序,还可以用在重传时去重 确认应答是机制中的核心 因为都需要依靠应答来拿到协议字段,从而判断是否触发机制 保证可靠性的策略也可以提高效率,比如: 流量控制,可以根据多个因素来动态调整数据发送量拥塞控制也是,让…

XSS(跨站脚本攻击)

1.什么是xss XSS全称&#xff08;Cross Site Scripting&#xff09;跨站脚本攻击&#xff0c;为了避免和CSS层叠样式表名称冲突&#xff0c;所以改为了 XSS&#xff0c;是最常见的Web应用程序安全漏洞之一,XSS是指攻击者在网页中嵌入客户端脚本&#xff0c;通常是JavaScript编写…

两句话让LLM逻辑推理瞬间崩溃!!

一道简单的逻辑问题&#xff0c;竟让几乎所有的LLM全军覆没&#xff1f; 对于人类来说&#xff0c;这个名为「爱丽丝梦游仙境」&#xff08;AIW&#xff09;的测试并不算很难—— 「爱丽丝有N个兄弟&#xff0c;她还有M个姐妹。爱丽丝的兄弟有多少个姐妹&#xff1f;」 稍加思考…

Git发布正式

一般我们开发都是在测试环境开发&#xff0c;开发完成后再发布到正式环境。 一.分支代码合并到主分支1.首先切换到自己的分支(比如分支叫&#xff1a;dev)git checkout dev2.把本地分支拉取下来git pull 或者 git pull origin dev3.切换到主分支mastergit checkout master4.更新…

Unity | Shader基础知识(番外:了解内置Shader-Standard<二>)

目录 前言 一、Standard参数详解 1.NormalMap法线贴图 2.HeightMap高度贴图 3.Occlusion遮挡贴图 4.DetailMask细节遮挡 5.Emission自发光 6.Tiling铺地砖和Offset偏移度 二、作者的碎碎念 前言 Unity | Shader基础知识(番外&#xff1a;了解内置Shader-Standard&#x…

在WSL2下配置Pytorch(Linux+Anaconda+PyTorch-GPU)

之前使用过双系统、虚拟机的ubunutu 效果都不是很好&#xff0c;要么切换系统太麻烦&#xff0c;要么太卡顿 最近在尝试WSL子系统&#xff0c;没有想到还是有很多坑 记录一下配置的过程 一、NVIDIA显卡的安装 因为WSL和Windows的显卡驱动不能互通&#xff0c;所以在子系统上需…

Redis的缓存击穿、缓存穿透和缓存雪崩是什么?怎么预防?

Redis的缓存击穿、缓存穿透和缓存雪崩是什么&#xff1f;怎么预防&#xff1f; 前言缓存击穿定义解决思路实现加锁设置过期时间Lua脚本刷新锁 缓存穿透定义实现 缓存雪崩定义解决思路 总结 前言 最近在CSDN上看到了一篇博客&#xff0c;Redis缓存击穿、雪崩、穿透&#xff01;…

双列集合 HashMap以及TreeMap底层原理

双列集合 特点&#xff1a; 双列集合一次需要存一对数据&#xff0c;分别为键和值 键不能重复&#xff0c;值可以重复 键和值是一一对应的&#xff0c;每个键只能找到自己对应的值 键和值这个整体在Java中叫做“Entry对象” Map的常见API Map是双列集合的顶层接口&#xff0c;…

第十一篇——信息增量:信息压缩中的保守主义原则

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 通过信息中的保守主义&#xff0c;我想到了现实中人的保守主义一样&#…

JavaScript前端技术入门教程

引言 在前端开发的广阔天地中&#xff0c;JavaScript无疑是最耀眼的一颗明星。它赋予了网页动态交互的能力&#xff0c;让网页从静态的文本和图片展示&#xff0c;进化为可以与用户进行实时交互的丰富应用。本文将带您走进JavaScript的世界&#xff0c;为您提供一个入门级的教…

文件操作(Python和C++版)

一、C版 程序运行时产生的数据都属于临时数据&#xff0c;程序—旦运行结束都会被释放通过文件可以将数据持久化 C中对文件操作需要包含头文件< fstream > 文件类型分为两种: 1. 文本文件 - 文件以文本的ASCII码形式存储在计算机中 2. 二进制文件- 文件以文本的二进…

【InternLM实战营第二期笔记】06:Lagent AgentLego 智能体应用搭建

文章目录 讲解为什么要有智能体什么是 Agent智能体的组成智能体框架AutoGPTReWooReAct Lagent & Agent LegoAgentLego 实操Lagent Web Demo自定义工具 AgentLego&#xff1a;组装智能体“乐高”直接使用作为智能体&#xff0c;WebUI文生图测试 Agent 工具能力微调 讲解 为…

DDMA信号处理以及数据处理的流程---原始数据生成

Hello&#xff0c;大家好&#xff0c;我是Xiaojie&#xff0c;好久不见&#xff0c;欢迎大家能够和Xiaojie一起学习毫米波雷达知识&#xff0c;Xiaojie准备连载一个系列的文章—DDMA信号处理以及数据处理的流程&#xff0c;本系列文章将从目标生成、信号仿真、测距、测速、cfar…

【VUE3 element时间选择器默认选择七天】

VUE3 element时间选择器默认选择七天 <el-date-pickerv-model"form.timeRange"type"datetimerange"start-placeholder"开始时间"end-placeholder"结束时间"format"YYYY-MM-DD HH:mm:ss"date-format"YYYY/MM/DD dd…

vivado HW_ILA_DATA、HW_PROBE

HW_ILA_DATA 描述 硬件ILA数据对象是ILA调试核心上捕获的数据的存储库 编程到当前硬件设备上。upload_hw_ila_data命令 在从ila调试移动捕获的数据的过程中创建hw_ila_data对象 核心&#xff0c;hw_ila&#xff0c;在物理FPGA上&#xff0c;hw_device。 read_hw_ila_data命令还…

定个小目标之刷LeetCode热题(12)

这是一道简单题&#xff0c;使用位运算中的异或运算即可&#xff0c;异或运算有以下性质&#xff1a; 1、任何数异或 0 结果仍然是原来的数&#xff0c;即 a⊕0a 2、任何数和其自身做异或运算&#xff0c;结果是 0 所以我们只需要让数组里的所有元素进行异或运算得到的结果就…

深入解析ETL与ELT架构:数据集成技术的演进与发展

摘要&#xff1a;随着大数据时代的到来&#xff0c;数据集成成为企业信息化建设的重要环节。本文将深入探讨ETL与ELT两种架构&#xff0c;分析它们在数据处理、性能、可扩展性等方面的差异&#xff0c;为企业数据集成提供技术指导。 一、引言 在大数据时代&#xff0c;企业需要…

【Vue】获取模块内的state数据

目标&#xff1a; 掌握模块中 state 的访问语法 尽管已经分模块了&#xff0c;但其实子模块的状态&#xff0c;还是会挂到根级别的 state 中&#xff0c;属性名就是模块名 使用模块中的数据 直接通过模块名访问 $store.state.模块名.xxx 通过 mapState 映射&#xff1a; 默认…

Java网络通信实现

UDP UDPServer import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket;public class UDPServer {public static void main(String[] args) throws IOException {System.out.println("UdpServer启动");// 创建upd套接字Data…