HNU算法设计与分析期末(2025年信安)

++都是我自己的答案,不一定正确,仅供参考++

1.A:和B:,这两个分别表示什么,哪个价值更高,为什么?

前一个表示渐进上界,后一个表示渐进下界

我写的前一个价值更高,因为我们更习惯考虑时间开销的上限来判断一个算法的可行性(前一个使用多一点)

2.分治法和动态规划的异同?为什么有些不能使用动规但是能使用分治?

我是这么回答的:

相同:都需要分解成子问题,都可以用来解决最优问题;

异:分治法的子问题相互独立互不重叠,动规的子问题有重叠;分治法自上而下递归,需要合并子问题,而动规自底向上计算,不需要合并子问题:分治法分治法不存储子问题的解,动规需要存储子问题。

为什么有些不能用动规可以用分治:因为有些问题不具备最优子结构和重叠子问题;或者有些问题不需要求最优解,这时候使用分治法

3.限界函数为什么重要?好的限界函数应该具备什么性质?

我的回答:

如果没有限界函数,往往需要遍历所有解空间数,可能达到指数或者阶乘级别,因此需要使用限界函数避免一些无效的搜索,减少时间开销。

性质:1.需要能够快速排除较多的无效探索,2.计算开销不能过大,否则会导致时间开销更多

4.使用分治法求解数组的最大连续和问题

这题最佳方法是动态规划,但是题目要求使用分治,我的写法:

首先可以分成三个部分:左,右,跨越左右

左右都可以直接使用递归实现

跨越左右的部分我是采用了双指针贪心法:先固定左指针在左边最右的位置,右指针在右边最左的位置,每次比较左右较大值,较大的一方加入sum,然后将指针朝边缘移动,并且比较sum和cross_max,使得cross_max最大。

最终返回max(left_max,right_max,cross_max)

5.给定一个m×n的二维数组grid,每个元素都是一个数字,然后计算从(0,0)到(m-1,n-1)的最小值(每次只能向右和向下,路过的位置加入到sum中)

这题是经典的动态规划,可以列出状态转移方程:

6.一辆车从起点出发,每次加油后可以行驶k公里,每两个加油站的距离保存在x数组中,问最少要加多少次油

贪心算法,每次直到油不够跑到下一个加油站的时候才加油

7.给定一个m×n的二维字符数组board,给定目标word(一维数组),要求从board中选择一个起点,每次可以朝周围四个方向选择,要求最终能按word的顺序遍历,并且不能重复使用已经使用的字符(位置)

使用回溯法,我的思路如下(给出伪代码):

cpp 复制代码
bool backtrace(char **board,char *word,int n,int m,int i ,int j,int k,bool *visit){
	if(k == word.size()) return true;
	int grid = {{1,0},{-1,0},{0,-1},{0,1}};
	for(int d = 0; d < 4; d++){
		ni = i + grid[d][0];
		nj = j + grid[d][1];
		if(ni < 0 || ni >=n || nj < 0 || nj >= m) continue;
		if(board[ni][nj] == word[k] && !visit[ni][nj]){
			k++;
			visit[ni][nj] = true;
			if(backtrace(board,word,n,m,ni,nj,k,visit)) return true;
			visit[ni][nj] = false;
			k--;
		}
	}
	return false;
} 

int main(){
	for(int i = 0; i < n; i ++){
		for(int j = 0; j < m; j++){
			backtrace(board,word,n,m,i,j,0,visit);
		}
	}
}

8.给定n个工人和n个任务,和costnn表示第i个工人干第j个任务的开销,使用分支限界法使得开销最少

这题可以使用优先队列的分支限界法,我在做的时候没有给出完整逻辑,大致逻辑如下:

定义一个最小堆min_heap,按照当前已经耗费+剩下工人每个人选剩下的最小耗费来进行比较,第一个完成分配的就是最终的结果。

在遍历时由于是排列,可以采取swap进行遍历,但是我在写的时候由于min_heap里面我设计了最小耗费和当前安排的工作数量,我加上了安排了工人vector<int> people,所以遍历时我使用find查看当前工人是否已经在people中来遍历。

给出伪代码:

cpp 复制代码
int BFS(int **cost,int n){
	min_heap<node> prior_q;
	for(int i = 0; i < n; i++){
		prior_q.push(node(cost[i][0]+last,1,i));//分别是累计开销,下一个执行任务,当前的工人 
	}
	while(!prior_q.empty()){
		curr_node = prior_q.front();
		prior_q.pop();
		if(curr_node.t == n) return curr_node.cost;
		for(int i = 0; i < n; i++){
			if(!curr_node.find(i)){
				prior_q.push(node(cost[i][t]+last,t+1,i));
			}
		}
	} 
}
相关推荐
GreenTea7 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
fqq38 小时前
力扣刷题前置Java语法
算法·leetcode·职场和发展
2501_9065651211 小时前
数学之美探究
算法
oier_Asad.Chen11 小时前
【洛谷题解/AcWing题解/OI学习笔记】洛谷P2868【USACO07DEC】Sightseeing Cows G(01分数规划求最大比率)
算法·图论·spfa·二分·负环
leisoo809713 小时前
财报数据怎么排雷本地化Python构建财务异常预警系统
人工智能·python·算法
luj_176815 小时前
塔防牌:策略与卡牌的智慧碰撞
服务器·c语言·开发语言·经验分享·算法
郝学胜-神的一滴15 小时前
干货版《算法导论》17:二叉树核心原理、遍历逻辑与高阶实操全解
数据结构·c++·python·算法·计算机·编程
爱编程的小新☆16 小时前
【LeetCode】从递归到 Flood Fill:5 道题吃透 DFS 的选择、回溯与标记
java·算法·leetcode·深度优先·回溯·flood fill
Water_Sunzhipeng16 小时前
2024牛客暑期多校训练营1
算法
hetao173383716 小时前
2026-08-09~08-14 hetao1733837 的刷题记录
c++·算法