python_1_常用算法

Posted PP笔记本

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python_1_常用算法相关的知识,希望对你有一定的参考价值。

常用算法

  • 穷举法。

  • 贪婪法 

  • 分治法 

  • 回溯法 

  • 动态规划 


1.穷举法

使用穷举法解决问题,基本上就是以下两个步骤:
确定问题的解(或状态)的定义、解空间的范围以及正确解的判定条件;
根据解空间的特点来选择搜索策略,逐个检验解空间中的候选解是否正确;


实例1:百钱百鸡问题

公鸡5元一只,母鸡3元一只,小鸡1元三只

用100元买100只鸡,请问公鸡/母鸡/小鸡各有多少只

for x in range(20): for y in range(33): z= 100- x- y if 5*x+3*y+z//3 == 100 and z % 3== 0: print(x,y,z)


实例2:五人分鱼问题

A、B、C、D、E五人在某天夜里合伙捕鱼 最后疲惫不堪各自睡觉


第二天A第一个醒来 他将鱼分为5份 扔掉多余的1条 拿走自己的一份


B第二个醒来 也将鱼分为5份 扔掉多余的1条 拿走自己的一份


然后C、D、E依次醒来也按同样的方式分鱼 问他们至少捕了多少条鱼

fish = 6while True: total = fish enough = True for _ in range(5): if (total - 1) % 5 == 0: total = (total - 1) // 5 * 4 else: enough = False break if enough: print(fish) break fish += 5


2.贪婪算法

贪婪算法(贪心算法)是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有利)的选择,从而希望能够导致结果是最好或者最优的算法。
贪婪算法所得到的结果往往不是最优的结果(有时候会是最优解),但是都是相对近似(接近)最优解的结果。


其基本的解题思路为:
1.建立数学模型来描述问题
2.把求解的问题分成若干个子问题
3.对每一子问题求解,得到子问题的局部最优解
4.把子问题对应的局部最优解合成原来整个问题的一个近似最优解

实例3:小偷偷东西

假设小偷有一个背包,最多能装20公斤赃物,他闯入一户人家,发现如下表所示的物品。很显然,他不能把所有物品都装进背包,所以必须确定拿走哪些物品,留下哪些物品

名称 价格(美元) 重量(kg)
电脑 200 20
收音机 20 4
175 10
花瓶 50 2
10 1
油画 90 9


class Thing(object): """物品"""
def __init__(self, name, price, weight): self.name = name self.price = price self.weight = weight
@property def value(self): """价格重量比""" return self.price / self.weight

def input_thing(): """输入物品信息""" name_str, price_str, weight_str = input().split() return name_str, int(price_str), int(weight_str)

def main(): """主函数""" max_weight, num_of_things = map(int, input().split()) all_things = [] for _ in range(num_of_things): all_things.append(Thing(*input_thing())) all_things.sort(key=lambda x: x.value, reverse=True) total_weight = 0 total_price = 0 for thing in all_things: if total_weight + thing.weight <= max_weight: print(f'小偷拿走了{thing.name}') total_weight += thing.weight total_price += thing.price print(f'总价值: {total_price}美元')

if __name__ == '__main__': main()


https://blog.csdn.net/SweetSeven_/article/details/95197131?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159391695019725250117737%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=159391695019725250117737&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~baidu_landing_v2~default-7-95197131.pc_v1_rank_blog_v1&utm_term=%E8%B4%AA%E5%A9%AA%E7%AE%97%E6%B3%95


3.分治法

字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。


分治法在每一层递归上都有三个步骤:
分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
合并:将各个子问题的解合并为原问题的解。


实例4:快速排序

选择枢轴对元素进行划分,左边都比枢轴小右边都比枢轴大


def quick_sort(items, comp=lambda x, y: x <= y): items = list(items)[:] _quick_sort(items, 0, len(items) - 1, comp) return items

def _quick_sort(items, start, end, comp): if start < end: pos = _partition(items, start, end, comp) _quick_sort(items, start, pos - 1, comp) _quick_sort(items, pos + 1, end, comp)

def _partition(items, start, end, comp): pivot = items[end] i = start - 1 for j in range(start, end): if comp(items[j], pivot): i += 1 items[i], items[j] = items[j], items[i] items[i + 1], items[end] = items[end], items[i + 1] return i + 1


4.回溯法

回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。
在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。


用回溯法解题的一般步骤:
针对所给问题,确定问题的解空间:首先应明确定义问题的解空间,问题的解空间应至少包含问题的一个(最优)解。
确定结点的扩展搜索规则。
以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

实例5:骑士巡逻
import sysimport time
SIZE = 5total = 0

def print_board(board): for row in board: for col in row: print(str(col).center(4), end='') print()

def patrol(board, row, col, step=1): if row >= 0 and row < SIZE and \ col >= 0 and col < SIZE and \ board[row][col] == 0: board[row][col] = step if step == SIZE * SIZE: global total total += 1 print(f'第{total}种走法: ') print_board(board) patrol(board, row - 2, col - 1, step + 1) patrol(board, row - 1, col - 2, step + 1) patrol(board, row + 1, col - 2, step + 1) patrol(board, row + 2, col - 1, step + 1) patrol(board, row + 2, col + 1, step + 1) patrol(board, row + 1, col + 2, step + 1) patrol(board, row - 1, col + 2, step + 1) patrol(board, row - 2, col + 1, step + 1) board[row][col] = 0

def main(): board = [[0] * SIZE for _ in range(SIZE)] patrol(board, SIZE - 1, SIZE - 1)

if __name__ == '__main__': main()

5.动态规划

基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。


动态规划的实现步骤:

划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。在划分阶段时,注意划分后的阶段一定要是有序的或者是可排序的,否则问题就无法求解。
确定状态和状态变量:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。当然,状态的选择要满足无后效性。
确定决策并写出状态转移方程:因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以如果确定了决策,状态转移方程也就可写出。但事实上常常是反过来做,根据相邻两个阶段的状态之间的关系来确定决策方法和状态转移方程。
寻找边界条件:给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。

实例6:子列表元素之和的最大值

子列表指的是列表中索引(下标)连续的元素构成的列表;列表中的元素是int类型,可能包含正整数、0、负整数;程序输入列表中的元素,输出子列表元素求和的最大值,例如:

输入:1 -2 3 5 -3 2

输出:8

输入:0 -2 3 5 -1 2

输出:9

输入:-9 -2 -3 -5 -3

输出:-2

def main(): items = list(map(int, input().split())) overall = partial = items[0] for i in range(1, len(items)): partial = max(items[i], partial + items[i]) overall = max(partial, overall) print(overall)

if __name__ == '__main__': main()




以上是关于python_1_常用算法的主要内容,如果未能解决你的问题,请参考以下文章

Python常用模块-摘要算法(hashlib)

[AndroidStudio]_[初级]_[配置自动完成的代码片段]

[AndroidStudio]_[初级]_[配置自动完成的代码片段]

[AndroidStudio]_[初级]_[配置自动完成的代码片段]

「Python 基础」常用模块

DBSCAN密度聚类算法(理论+图解+python代码)