湘潭大学软件工程算法设计与分析考试复习笔记(六)

文章目录

回顾

说明

这篇笔记是关于 40 分的程序填空的。

前面涉及代码的部分

湘潭大学软件工程算法设计与分析考试复习笔记(二):这篇博客里面有一些代码,可以选择性地记一记。

因为代码填空涉及的内容比较广泛,下面主要是从ppt里面摘录出来。

第一章

没有代码填空,非常轻松。

第二章

汉诺塔问题

cpp 复制代码
void Hanoi(int n, int Fr, int To, int As)
          {
               if  (n > 0) {
                    Hanoi(n--1, Fro, Ass, To);
                    Move(Fro, To);
                    Hanoi(n--1, Ass, To, Fro)}
           }

正整数的划分

cpp 复制代码
q(n, m) { 
       if (n < 1) || (m < 1)      return 0;
       if (n == 1) || (m == 1)  return 1;
       if (n == 1) || (n < m)    return 1 + q(n, n--1);
       return q(n, m--1) + q(n--m, m);  }

Hilbert图案

cpp 复制代码
A(i) { 
   if  (i > 0) { D(i -- 1); x = x -- h;  ploting(x, y) ; 
      A(i -- 1);   y = y -- h;  ploting(x, y) ;
      A(i -- 1);   x = x + h;  ploting(x, y) ;
       B(i -- 1); }}
  //*ploting(x, y)是从画笔现行坐标到坐标(x, y)画条直线

Koch 曲线

cpp 复制代码
Koch(L, i) { //*L为长度,i为级数
  if (i == 0) Line(L) //*i为0,画条长为L的线段
  else {Koch(L/3, i -- 1);
           Turn(60);  Koch(L/3, i -- 1);
           Turn(--120);  Koch(L/3, i -- 1);
           Turn(60);  Koch(L/3, i -- 1);}}
Draw-Koch(L, θ, n) {//*将角度初始化为θ;
     Turn(θ);  Koch(L, n);}//*然后再画曲线。

二分搜索有序表

cpp 复制代码
Binary-Search(L, n, z)
{k = 1; m = n; //*k和m分别为搜索部分的首和尾
 flag = 0; //*找到标志初始为0
 while (k <= m && flag = 0) {
     j = (k + m) / 2 ; //*取中点下标 
    if (z == L[j]) flag = 1 //* 找到了标志为1
  else if (z < L[j]) m = j -- 1 //*小于中点,尾前移
      else k = j + 1 //*大于中点,首后移
} 

一维最接近点对算法

有一些特殊符号显示不出来。所以这里把课件的截图也放在这儿了。

cpp 复制代码
bool Cpair1(S, d)
{
   n = |S|;
   if (n < 2) { d = ∞; return false }
   m = S中各点的坐标的中位数;
   构造S1和S2; // S1={xS | xm}, S2={xS | x>m}
   Cpair1(S1, d1); 
   Cpair1(S2, d2);  //分别求S1和S2的最接近点对
   p=max{S1}; q =min{S2}; d = mim{d1, d2, q -- p};
   return true 
}

平面最接近点对的算法

不是那种非常标准的代码,应该是为了方便我们理解写的伪代码

第三章

Prim算法的实现

cpp 复制代码
Prim(int n, Type **c) {
	int j = 1; s[j] = true; 
	for (int i = 2; i <= n;  i++) { 
		closest[i] = 1; 
		lowcost[i]=c[1][i];
		s[i]=false;
	}
	for (int i = 1; i < n;  i++) {
		min= inf; 
		for (int k = 2; k <= n;  k++) {
    		if (lowcost[k]<min&&!s[k]){
    			min = lowcost[k]; 
    			j = k;
    		} 
	s[j] = true;                         
	for (int k = 2; k <= n;  k++) {
    	if (c[j][k]< lowcost[k]&&!s[k]){
    		lowcost[k] = c[j][k]; 
    		closest[k] = j;
       }
    }
} 

Kruskal算法的实现

cpp 复制代码
Kruskal(int n, **e)  {
  Sort(e, w); //将边按权重从小到大排序
  initialize(n); //初始时每个顶点为一个集合
  k = 1; //k累计已选边的数目,
  j = 1;  //j为所选的边在e中的序号
  while (k < n) //选择n -- 1条边
    {a = Find(e[j][u]); b = Find(e[j][v]); 
   //找出第j条边两个端点所在的集合
     if (a != b) {t[k++] = j; Union(a, b)}
   //若不同,第j条边放入树中并合并这两个集合
     j++ }} //继续考察下一条边

Dijkstra 算法

第四章

消除重复的矩阵连乘算法

最优三角剖分的算法

cpp 复制代码
Void MinWeightTriangulation(int n, Type **t, int **s)
 {  for (int i = 1; i <= n; i++) t[i][i] = 0; 
     for (int r = 2; r <= n; r++) 
        for (int i = 1; i <= n -- r +1; i++) {
           int j = i + r -- 1;
           t[i][j] = t[i+1][j] + w(i--1, i, j);
           s[i][j] = i; 
           for (int k = i + 1; k < j; k++) {
              int u = t[i][k] + t[k+1][j] + w(i--1, k, j); 
              if (u < t[i][j]) {t[i][j] = u; s[i][j] = k;}
}}} //程序中红色的部分为改动的地方

动态规划法求序列相似性

第五章

树搜索的一般形式

cpp 复制代码
SearchTree(Space T)//表L用来存放待考察的结点
{unfinish = true; L = T.initial; 
// unfinish表示搜索未结束,先将初始状态放入L
while (unfinish || L≠Φ) {
     a = L.first; //从L中取出第一个元素
     if (a is goal) unfinish = false //若a是终态则结束
 else Control-put-in(L, Sons(a));
} //否则,将a的儿子们以某种控制方式放入L中

迭代回溯法的一般形式

用末尾标记的迭代回溯

数字的全排列





n 皇后





TSP 递归回溯






用回溯法解0-1背包问题

cpp 复制代码
Try(s){
 for (i = 0; i < 2; i++)
   if  (Accept(i)) {
        Record(s, i);
       if (s = = n) {if  ( better ) TakeNewChoice( );}  
   else Try(s+1);
       Move-off(s, i);}
 return } 

0-1背包问题的迭代实现

cpp 复制代码
Backtrack(Tree T) {
 j = 1; L.Push(--1, 0, 1);
  while (L≠Φ) {
    a = L.Pop( ); 
    if (a = = --1) {Move-off(j, N[j]); j-- --;}
else if (W+w[j]*a <= C) {Record(a);
        if (j = = n ) {if (V < NV) TakeNewChoice( );}
 else {j++; L.Push(--1, 0, 1);}
}}}

第六章

求传递闭包的Warshall算法

cpp 复制代码
for (i = 1; i <= n; i++)
         for (j = 1; j <= n; j++)
              if (M[j][i] == 1) 
                    for (k = 1; k <= n; k++)
                          M[j][k] = M[j][k] + M[i][k]

ppt 上面只有这个代码。之后会补充一些,在博客的最后面。

第七章

直接用概率进行数值计算

cpp 复制代码
double Darts (int n) {double x, y;  int k = 0; 
  static RandomNumber dart;
  for (int i=1; i<=n; i++) {x=dart.fRandom();   
     y=dart.fRandom(); if (y<=f(x)) k++;}
  return k/double(n); }

"洗牌"后的快速排序

cpp 复制代码
void Shuffle(Type a[], int n) { //随机洗牌算法
   static RandomNumber md;
   for (int i = 1; i < n; i++) {
         int j = md.Random(n -- i + 1) + i;
         Swap(a[i], a[j]); }}
Void QuiksortByShuffle(Type a[], int n) {
    Shuffle(a, n); //将数组a洗牌
    Quiksort(a, n); }

随机抽样

cpp 复制代码
int RandomSampling(S[n], A[m], m) {
  mark[1..n] = False;  count=0;
  while(count < m) {
      r = random(1, n);
      if (mark[r] == False) {
          count++;
          A[count]=S[r];
          mark[r]=True; }}}

Fermat素数测试法

cpp 复制代码
Bool Fermat_Prime(int n) {
   a = 2; power = n -- 1; other = 1;
  while(power > 1)  {
    if (power % 2 = = 1) {other *= a; other %= n;}
    power /= 2;   a = a * a  %  n;}
  if  (a * other  %  n == 1) return True;
  return False;
}

Miller-Rabin素数判定概率算法

cpp 复制代码
Bool  Miller_Rabin_Prime(int n){
 b[1 .. m] = RandomSampling(n, m); 
 /*随机选取m个大于1小于n的无重复的自然数
for (j = 1; j <= m;  j++)
      if (W(b[j]) 满足)  return False;
 return True;
}
若m = 100,则n不是素数的概率小于1/2100。

模拟退火算法的框架

cpp 复制代码
k = 0; i = i0; t = t0; //初始化
while (不满足停止准则) {
   Gen(Si); //产生i的邻域Si,|Si|=Lk
   for (j∈Si) //用Metropolis准则对Si中的
        if (f(i) < f(j)) i = j; //每个状态j检测是否可替代i
     else if (exp((f(i) -- f(j))/ t) > random(0, 1)) i = j;
   k = k + 1; t = tk; // 降温;进入下一轮迭代
 }       

第八章

没有代码

补充

最佳调度

cpp 复制代码
long f(int n) {
    if (n < 2) return n;
    long sum = 1;
    for (int i = 1 ; i <= n - 1; i++)
        sum += f(i);
    return sum;
 }

备忘录方法

cpp 复制代码
 Long dp[max]
 long f1(int n) {
    dp[1] = 1;
    dp[2] = 2;
    if (n <2) { 
        return dp[n];
    }
    if (dp[n] > 0) return dp[n];
    long sum = 1;
    for (int i = 1 ; i <= n - 1; i++)
        sum += f1(i);
    dp[n] = sum;
    return dp[n];
 }

上台阶

cpp 复制代码
#include<iostream>
#include<cmath>
using namespace std;
int dp[107];
int main() {
	int n, m;
 	cin >> n >> m;
 	dp[0] = 1;
 	for (int i = 1; i <= n; i++) {
 		for (int j = 1; j <= m; j++) {
			 if (i < j)break;
 			dp[i] += dp[i - j];
 		}
 	}
 	cout << dp[n];
 	return 0;
}
相关推荐
Jerry4 小时前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry5 小时前
LeetCode 459. 重复的子字符串
算法
海石8 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石8 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
Jerry10 小时前
LeetCode 151. 反转字符串中的单词
算法
β添砖java11 小时前
2025最新快速构建企业级虚拟专用网络环境学习笔记
笔记·学习
qianpeng411 小时前
IDA PRO笔记
笔记
a11177613 小时前
LM 算法迭代过程动画演示(SLAM)
算法
头茬韭菜13 小时前
Context 的生死抉择:四层压缩、截断算法与 Session Memory
算法·ai
Jerry13 小时前
LeetCode 541. 反转字符串 II
算法