网络知识 娱乐 算法设计与分析期末复习大全(算法填充题+综合题)

算法设计与分析期末复习大全(算法填充题+综合题)

目录

  • 算法填充题
    • 子集生成问题
    • 全排列生成问题
    • 哈密顿回路问题
    • 八皇后问题
    • 最大子段和问题
    • 最长公共子序列问题
  • 综合题
    • 1. 贪心法(设计+证明)
    • 2.0/1背包问题(证明+动态规划法计算过程)
    • 3.货币兑付问题(证明+动态规划法计算过程)
    • 4.多段图最短路径问题(证明+动态规划法计算过程)
    • 5.多机调度或批处理调度(限界函数设计+搜索过程)
    • 6.TSP问题(搜索空间树及算法)

算法填充题

子集生成问题

  • 问题描述

子集生成是暴力求解算法中比较经典的问题,给出集合A,求得相应的子集,进行打印。

  • 解法一:增量构造法
#include
#include
#include
#include
using namespace std;
#define INF 300 
int A[100]; 
void print_subset(int n,int *A,int cur)
{
	for(int i=0;i<cur;i++)
		printf("%d ",A[i]);//输出子集 当前的集合 
	printf("n");
	int s=cur?A[cur-1]+1:0;//确定当前最小的可能值  如果这里不是 这里特殊的就是cur==0时 其他的就是选比前一个大1的 
	for(int i=s;i<n;i++)
	{
		A[cur]=i;//将i加入当前的集合
		print_subset(n,A,cur+1);// 递归构造子集 
	 } 
}
int main()
{
	int n;scanf("%d",&n);
	print_subset(n,A,0); 
}
  • 解法二:位向量法
#include
#include
#include
#include
using namespace std;
#define INF 300 
int B[100]; 
void print_subset(int n,int *B,int cur)
{
	if(cur==n)
	{
		for(int i=0;i<cur;i++)
			if(B[i])printf("%d ",i);
		printf("n");
		return ;
	}
	B[cur]=1;
	print_subset(n,B,cur+1);//选 
	B[cur]=0;
	print_subset(n,B,cur+1);//不选 
}
int main()
{
	int n;scanf("%d",&n);
	print_subset(n,B,0); 
}
  • 解法三:二进制法(简单)
#include
#include
#include
#include
using namespace std;
#define INF 300 
int B[100]; 
void print_subset(int n,int s)
{
	for(int i=0;i<n;i++)
		if(s&(1<<i))printf("%d ",i);
	printf("%n");
}
int main()
{
	int n;scanf("%d",&n);
	for(int i=0;i<(1<<n);i++)
		print_subset(n,i); 
}
原文链接:https://blog.csdn.net/liyanfeng1996/article/details/52821868

全排列生成问题

  • 问题描述

对于给定的集合A{a1,a2,…,an},其中的n个元素互不相同,如何输出这n个元素的所有排列(全排列)。

  • 算法实现 (递归)
#include 
using namespace std;
const int maxn=1000;
int a[maxn];
void swap(int i,int j)
{
    int temp=a[i];
    a[i]=a[j];
    a[j]=temp;
}
void perm(int k,int m,int pk,int pm)//k,m一般取起始和终点位置,k是不断变化的
{
    //k是中间变量,m初始化为参与拍列元素的起始坐标和终止坐标
    //pk和pm分表表示参与排列元素的起始和终止坐标,不变的量。
    if(k==m){//当k换到最后的时候,便是出口,是已经交换好的序列
        for(int i=pk;i<=pm;i++) cout<<a[i];
        cout<<endl;
    }
    else{
        for(int i=k;i<=m;i++){
            swap(k,i);//一部分一部分的交换,最后进行还原
            perm(k+1,m,pk,pm);//模拟一下过程,一开始求解N确定一个元素后,求解N-1,依次类推。
            swap(k,i);//还原
        }
    }
}
int main()
{
    int x;
    cin>>x;
    for(int i=1;i<=x;i++)
        a[i]=i;
    perm(1,x,1,x);
    return 0}
原文链接:https://blog.csdn.net/qq_29980371/article/details/72553303

哈密顿回路问题

  • 问题描述

在这里插入图片描述

  • 算法
    在这里插入图片描述

  • 算法实现

采用邻接矩阵存储,数组 arc[n][n] 存储顶点之间的边的情况,为了避免在函数之间传递参数,将数组arc设为 全局 变量,设数组 x[n] 表示哈密顿回路经过的顶点。

在这里插入图片描述

八皇后问题

  • 问题描述

在8 x 8的棋盘上摆放8个皇后,而且八个皇后中的任意两个是不能处于同一行、同一列、或同一斜线上。也可以拓展到n皇后问题,即在n✖n的棋盘上摆放n个皇后,使任意两个皇后都不能处于同一行、同一列或同一斜线上。

  • 算法
    在这里插入图片描述

  • 算法实现

皇后k摆放在k行x[k]列的位置

在这里插入图片描述
在这里插入图片描述

最大子段和问题

  • 问题描述
    在这里插入图片描述
  • 算法实现

变量center表示序列的中间位置,数组 a[n] 存放整数序列

在这里插入图片描述

最长公共子序列问题

  • 问题描述
    在这里插入图片描述
  • 算法实现
    在这里插入图片描述

综合题

1. 贪心法(设计+证明)

贪心算法的设计思想:

  • 贪心算法在解决问题的策略上目光短浅,只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。换言之,贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优。贪心算法对于大部分的优化问题都能产生最优解,但不能总获得整体最优解,通常可以获得近似最优解

贪心算法的证明:

在这里插入图片描述
在这里插入图片描述

2.0/1背包问题(证明+动态规划法计算过程)

  • 证明(反证法
    在这里插入图片描述
  • 动态规划法计算过程

在这里插入图片描述

3.货币兑付问题(证明+动态规划法计算过程)

  • 题目: 在面值为(v1, v2, …, vn)n种货币中,需要支付y值的货款,应如何支付才能使货币支付的张数最少。设计动态规划算法求解该问题。

  • 证明
    在这里插入图片描述

  • 解决
    在这里插入图片描述
    示例:面值(1, 2, 5, 10),支付8
    在这里插入图片描述
    示例:面值(2, 5, 10),支付8
    在这里插入图片描述

4.多段图最短路径问题(证明+动态规划法计算过程)

  • 问题 在这里插入图片描述

  • 证明 在这里插入图片描述

  • 动态规划法计算过程
    在这里插入图片描述
    在这里插入图片描述

5.多机调度或批处理调度(限界函数设计+搜索过程)

  • 问题描述
    在这里插入图片描述

  • 限界函数设计
    在这里插入图片描述
    在这里插入图片描述

  • 搜索过程
    在这里插入图片描述
    (1)在根结点,将sum1和sum2分别初始化为0,估算目标函数的上界为41,将根结点加入待处理结点表PT.
    在这里插入图片描述

6.TSP问题(搜索空间树及算法)

  • 问题描述 假设有一个旅行商要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。旅行商有一个要访问城市的列表和每两个城市之间旅行的开销。需要求出开销最短的一种走法。
  • 搜索空间树
    在这里插入图片描述
  • 算法
    在这里插入图片描述