【算法】算法设计与分析 期末复习总结

第一章 算法概述

  • 时间复杂度比大小,用代入法,代入2即可。
  • 求渐进表达式,就是求极限,以极限为O的括号;
  • O是指上界,Ω是指下界,θ是指上下界相等,在这里,可以这样理解:
  1. f(n) = O(g(n)) 意味着 g(n) 在 n 趋近于无穷大时比 f(n) 大;
  2. f(n) = Ω(g(n)) 意味着 g(n) 在 n 趋近于无穷大时比 f(n) 小;
  3. f(n) = θ(g(n)) 意味着 g(n) 在 n 趋近于无穷大时和 f(n) 同阶;

第二章 递归与分治

主定理要掌握,选择题必考:

填空有一道二分搜索,掌握简单版和改进版即可:

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;
int n, m, a[N], x;

int bisearch(int x, int a[], int left, int right) {
    if (left > right)
        return -1;
    int middle = (left + right) / 2;
    if (a[middle] == x)
        return middle;
    else if (a[middle] < x)
        return bisearch(x, a, left, middle - 1);
    else
        return bisearch(x, a, middle + 1, right);
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    while (m--) {
        cin >> x;
        cout << bisearch(x, a, 0, n - 1) <<endl;
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;
int n, m, a[N], x;

pair<int, int> bs(int x, int a[], int left, int right) {
	if (left > right) {
		pair<int, int> p(right, left);
		return p;
	}
	int middle = (left + right) / 2;
	if (a[middle] == x) {
		pair<int, int> p(middle, middle);
		return p;
	}
	else if (a[middle] < x)
		return bs(x, a, middle + 1, right);
	else
		return bs(x, a, left, middle - 1);
} 

int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		cin >> a[i];
	while (m--) {
		cin >> x;
		pair<int, int> p = bs(x, a, 0, n - 1);
		cout << p.first << " " << p.second << endl;
	}
	return 0;
}

接着是排序,快速排序和归并排序的平均时间复杂度都为O(n logn),快排在最坏情况下的时间复杂度是O(n^2)。

知道中位数概念,一组个数为n的数中,当下标k = (n + 1) / 2时,称为找中位数。

归并的趟数是 logn ,归并的复杂度是 O(n logn)。

第三章 动态规划

0-1背包问题

题目

给定n(n<=100)种物品和一个背包。物品i的重量是wi(wi<=100),价值为vi(vi<=100),背包的容量为C(C<=1000)。
应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有两个选择:装入或不装入。不能将物品i装入多次,也不能只装入部分物品i。

输入格式:

共有n+1行输入:
第一行为n值和c值,表示n件物品和背包容量c;
接下来的n行,每行有两个数据,分别表示第i(1≤i≤n)件物品的重量和价值。

输出格式:

输出装入背包中物品的最大总价值。

输入样例:

在这里给出一组输入。例如:

5 10
2 6
2 3
6 5
5 4
4 6
输出样例:

在这里给出相应的输出。例如:

15
思路

假如现在有五个物品要选,这五个按顺序排下来,从第一个到第五个的最佳选择方案,相当于下面两种的择优选择:

  1. 不选第一个+后四个的最佳选择方案;
  2. 选第一个+后四个的最佳选择方案;

所以我们发现这是一个具有最优子结构性质的题目,同时也有重合子问题,于是我们可以用动态规划的方法来做。

作为动态规划,我们要严格按照三步走的格式来做:

首先,状态表示,我们设置一个二维数组m[i][j],作为从第i个到最后一个的最佳选择,同时剩余容量为j;

接着,递归方程,m[i][j] = max ( m[i + 1][j] , m[i + 1][j - w[i]] + v[i] ),也就是从不加第i个的,和加了第i个的这两个方案里选一个总价值最大的;

最后,边界条件,当我们的i为最后一个时,也就是i = n,此时容量从0到最大都可以进行赋值,也就是m[n][j] 的赋值,如果最后一个的重量不比c大,那就设置为这个的价值,如果比c小,就设置为0,注意边界条件在填表时要先写。

现在我们来研究一下最佳方案要怎么打印出来,也就是输出最佳选择组合的各个物品的下标。此时因为dp表已经填完了,所以可以让i从最小开始,我们依次判断即可,怎么判断呢?

直接看物品重量是否不超过剩余重量即可,剩余重量要另起一个变量remain,外层是物品的循环,里面第一重判断是有没有超重,第二重判断是加这个物品是不是比没加要好,把上面max里面的两个照抄即可。

都满足条件,就打印出这个物品的下标,然后使得remain减去这个物品的重量。

代码
#include<bits/stdc++.h>
using namespace std;

const int N = 100;

int n, c;
int w[N], v[N];
int m[N][N];

void dp() {
	for (int j = 0; j <= c; j++) {
		if (j >= w[n])
			m[n][j] = v[n];
		else
			m[n][j] = 0;
	}
	
	for (int i = n; i >= 1; i--) {
		for (int j = 0; j <= c; j++) {
			if (j >= w[i])
				m[i][j] = max(m[i + 1][j], m[i + 1][j - w[i]] + v[i]);
			else
				m[i][j] = m[i + 1][j];
		}
	}
	cout << m[1][c];
}

void print() {
	int remain = c;
	for (int i = 1; i <= n; i++) {
		if (remain >= w[i]) {
			if (m[i + 1][remain] < m[i + 1][remain - w[i]] + v[i]) {
				cout << i << ' ';
				remain -= w[i];
			}
		}
	}
	cout << endl;
}

int main() {
	cin >> n >> c;
	for (int i = 1; i <= n; i++)
		cin >> w[i] >> v[i];
	dp();
	print();
	return 0;
} 

第四章 贪心算法

选择当前看来最好的方案,这个的题目实在太简单了,不写思路。

题目

有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小。

输入格式:

共两行,第一行为n(1≤n≤1000);第二行分别表示第1个人到第n个人每人的接水时间T1,T2,…,Tn,每个数据之间有1个空格。

输出格式:

输出为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。

输入样例:
10
56 12 1 99 1000 234 33 55 99 812
输出样例:
291.90

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 1010;
int n;
int t[N];

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> t[i];
	sort(t + 1, t + n + 1);
	int total = 0;
	int wait = t[1];
	for (int i = 2; i <= n; i++) {
		total += wait;
		wait += t[i];
	}
	cout << fixed << setprecision(2) << 1.0 * total / n;
	return 0;
}

第五章 回溯法

子集和问题

题目

设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,使S1中的元素之和为c。试设计一个解子集和问题的回溯法,并输出利用回溯法在搜索树(按输入顺序建立)中找到的第一个解。

输入格式:

输入数据第1行有2个正整数n和c,n表示S的大小,c是子集和的目标值。接下来的1行中,有n个正整数,表示集合S中的元素。
是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。

输出格式:

输出利用回溯法找到的第一个解,以空格分隔,最后一个输出的后面有空格。当问题无解时,输出“No Solution!”。

输入样例:

在这里给出一组输入。例如:

5 10
2 2 6 5 4
输出样例:

在这里给出相应的输出。例如:

2 2 6

思路

这道题是在一堆数里面选择出一组加起来等于目标数的,用回溯法来做就是画出一棵二叉树,每一层树枝代表一个数字,如果选了这个数字,就顺着左子树往下走,没选就顺着右子树往下走,直到最底下,每次选择与否都要记录下来,还得记录当前的数字之和,如果走到叶子时数字之和等于目标数,就可以输出这组数了。

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 1000;

int n, c; // 数字个数,目标数 
int a[N], x[N]; //保存数字的数组,表示数字被选与否状态的数组
int sum = 0, remain = 0; //当前已选数字之和,当前剩余数字之和

void backtrack(int t) {
	if (t > n) {
		if (sum == c) {
			for (int i = 1; i <= n; i++) {
				if (x[i] == 1) 
				    cout << a[i] << " ";
			}
			cout << endl;
			exit(0);
		}
		return;
	}
	
	remain -= a[t];
	if (sum + a[t] <= c) {
		x[t] = 1;
		sum += a[t];
		backtrack(t + 1);
		sum -= a[t];
	}
	if (sum + remain >= c) {
		x[t] = 0;
		backtrack(t + 1);
	}
	remain += a[t];
} 

int main() {
	cin >> n >> c;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		remain += a[i];
	}
	backtrack(1);
	cout << "No Solution!" << endl;
	return 0;
}

第六章 分支限界法

分支限界法和回溯法的区别:

回溯法的求解目标是找出解空间中满足约束条件的所有解,而分支限界法的求解目标是找出满足约束条件的一个解,或是在满足约束条件的解中找出使某一目标函数达到极大或极小的解,即在某种意义下的最优解;

回溯法以深度优先的方式搜索解空间,分支限界法则以广度优先或以最小耗费优先的方式搜索解空间,分支限界法的搜索策略是,在扩展结点处,先生成其所有子结点,再从当前的活结点表中选择下一个扩展结点。

6.1 分支限界法的基本思想

分支限界法与回溯法的主要区别在于它们对当前扩展结点所采用的扩展方式不同。

搜索方式是广度优先或最小耗费(最大效益)优先。

1. 队列式(FIFO)分支限界法

按队列的先进先出原则选取下一个结点为当前扩展结点。

2. 优先队列式分支限界法

按优先队列中规定的结点优先级选取优先级最高的下一个结点成为当前的扩展结点。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SwiftUI之深入解析如何创建一个灵活的选择器

一、前言 在 Dribbble 上找到的设计的 SwiftUI 实现时&#xff0c;可以尝试通过一些酷炫的筛选器扩展该项目以缩小结果列表。筛选视图将由两个独立的筛选选项组成&#xff0c;两者都有一些可选项可供选择。但是&#xff0c;在使用 UIKit 时&#xff0c;总是将这种类型的视图实…

智能分析网关V4智慧港口码头可视化视频智能监管方案

一、需求背景 近年来&#xff0c;水利港口码头正在进行智能化建设&#xff0c;现场管理已经是重中之重。港口作为货物、集装箱堆放及中转机构&#xff0c;具有昼夜不歇、天气多变、环境恶劣等特性&#xff0c;安全保卫工作显得更加重要。港口码头的巡检现场如何高效、快捷地对…

指令周期流程图相关题目

已知CPU结构如下图所示&#xff0c;其中包括一个累加器AC、一个状态寄存器和其他几个寄存器。各部分之间的连线表示数据通路&#xff0c;箭头表示信息传递方向。试完成以下工作&#xff1a;①写出图中四个寄存器A、B、C、D的名称和作用&#xff1b;②简述完成指令ADD Y的数据通…

Spark Streaming与数据源连接:Kinesis、Flume等

在大数据领域&#xff0c;实时数据处理变得越来越重要。Apache Spark Streaming是一个强大的工具&#xff0c;可用于处理实时数据流。本文将介绍如何使用Spark Streaming连接各种数据源&#xff0c;包括Amazon Kinesis、Apache Flume等&#xff0c;并提供详细的示例代码&#x…

图解设计模式-中介者模式(Mediator)

中介者模式 定义 使用一个中介者对象&#xff08;mediator&#xff09;集中封装多个具有依赖/关联关系的对象&#xff08;colleague&#xff0c;同事对象&#xff09;之间的交互&#xff0c;使各对象之间不再互相引用&#xff0c;降低对象之间的强耦合程度&#xff0c;对象之…

【Python案例实战】水质安全分析及建模预测

一、引言 1.水资源的重要性 水是生命之源,是人类生存和发展的基础。它是生态系统中不可或缺的组成部分,对于维系地球上的生命、农业、工业、城市发展等方面都具有至关重要的作用。 2.水质安全与人类健康的关系 水质安全直接关系到人类的健康和生存。水中的污染物和有害物…

面向对象的三大特征之一多态

多态 概念 多态是同一个对象&#xff0c;在不同时刻表现出来不同的形态&#xff0c;称之为多态。 例如&#xff1a;水&#xff0c;我们把水理解成为一个对象&#xff0c;而水会有不同的形态&#xff0c;比如 液态水、冰块、水蒸气 多态的前提 有继承/实现关系&#xff08;继承…

新手深入浅出理解PyTorch归一化层全解析

目录 torch.nn子模块normal层详解 nn.BatchNorm1d BatchNorm1d 函数简介 函数工作原理 参数详解 使用技巧与注意事项 示例代码 nn.BatchNorm2d BatchNorm2d 函数简介 函数工作原理 参数详解 使用技巧与注意事项 示例代码 nn.BatchNorm3d BatchNorm3d 函数简介 参…

KeyError: ‘model_state_dict‘

问题 加载模型权重文件时获取model_state_dict键失败 解决 单步调试发现保存模型权重时正确保存了该键值对&#xff0c;再次调试时发现莫名奇妙又没错了 首先确认保存模型时的状态字典键名&#xff1a;确保在保存模型权重时&#xff0c;正确地使用了 model.state_dict() 方法…

飞书文档如何转markdown

飞书文档如何转markdown 实现效果实现步骤其他方法 实现效果 导出的结果挂在这了 https://thinkasany.github.io/docs/#/ 实现步骤 以https://upyun.feishu.cn/docx/KERsd1DpioPb1xxye9VcuXbhnBC这篇文章为例 使用工具 https://github.com/Wsine/feishu2md&#xff0c;提供了…

【计算机算法设计与分析】棋盘覆盖问题(C++_分治法)

文章目录 题目描述测试样例算法原理算法实现参考资料 题目描述 在一个 2 k 2 k 2^k \times 2^k 2k2k个方格组成的棋盘中&#xff0c;若恰有一个方格与其他方格不同&#xff0c;则称该方格为一个特殊方格&#xff0c;且称该棋盘为一个特殊棋盘。显然&#xff0c;特殊方格在棋…

腾讯云Centos9使用docker的方式安装APISIX

在虚拟机中安装Docker、Docker-compose 安装Docker 清除旧版本的docker yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 安装docker的依赖 yum install -y yum-utils device-ma…

在k8s集群中部署多nginx-ingress

关于ingress的介绍&#xff0c;前面已经详细讲过了&#xff0c;参考ingress-nginx详解和部署方案。本案例ingress的部署使用deploymentLB的方式。 参考链接&#xff1a; 多个ingress部署 文章目录 1. 下载ingress的文件2. 文件资源分析3. 部署ingress3.1 部署第一套ingress3.1…

快速、准确地检测和分类病毒序列分析工具 ViralCC的介绍和详细使用方法,fudai shiyong ijaoben

介绍 viralcc是一个基因组病毒分析工具&#xff0c;可以用于快速、准确地检测和分类病毒序列。 github&#xff1a;dyxstat/ViralCC: ViralCC: leveraging metagenomic proximity-ligation to retrieve complete viral genomes (github.com) Instruction of reproducing resul…

BERT(从理论到实践): Bidirectional Encoder Representations from Transformers【3】

这是本系列文章中的第3弹,请确保你已经读过并了解之前文章所讲的内容,因为对于已经解释过的概念或API,本文不会再赘述。 本文要利用BERT实现一个“垃圾邮件分类”的任务,这也是NLP中一个很常见的任务:Text Classification。我们的实验环境仍然是Python3+Tensorflow/Keras…

sql:定时执行存储过程(嵌套存储过程、使用游标)

BEGINDeclare FormNo nvarchar(20) --单号Declare Type nvarchar(50) --类型Declare PickedQty float -Declare OutQty float Declare 生产量 floatDeclare 已装箱数量 float Declare 已入库数量 floatDeclare 损耗数量 float Declare 退货品出库数量 intdeclare k c…

DrGraph原理示教 - OpenCV 4 功能 - 膨胀腐蚀

在二值图的结果基础上&#xff0c;可针对性处理。 这些处理有些是概念上的&#xff0c;有些是原理上的&#xff0c;也有形态上的&#xff0c;那就看用途与目的了。 本质上还是对二值图的黑白点进行处理&#xff0c;以用于图像增强、边缘检测、图像分割等多个领域。比如膨胀与腐…

ubuntu创建pytorch-gpu的docker环境

文章目录 安装docker创建镜像创建容器 合作推广&#xff0c;分享一个人工智能学习网站。计划系统性学习的同学可以了解下&#xff0c;点击助力博主脱贫( •̀ ω •́ )✧ 使用docker的好处就是可以将你的环境和别人的分开&#xff0c;特别是共用的情况下。本文介绍了ubuntu环境…

信息论与编码期末复习——概念论述简答题(一)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

C++基础语法——基本知识、数据类型、运算符及程序流程结构

本专栏记录C学习过程包括C基础以及数据结构和算法&#xff0c;其中第一部分计划时间一个月&#xff0c;主要跟着黑马视频教程&#xff0c;学习路线如下&#xff0c;不定时更新&#xff0c;欢迎关注。 当前章节处于&#xff1a; >第1阶段-C基础入门 ---------第2阶段实战-通讯…