精华内容
下载资源
问答
  • 算法设计与分析期末考试试卷(D卷)(含答案).doc
    千次阅读
    2021-07-15 03:34:18

    算法设计与分析期末考试试卷(D卷)

    一、选择题(0分,每题分)

    。D

    A.n2/2 + 2n的渐进表达式上界函数是O(2n)

    B.n2/2 + 2n的渐进表达式下界函数是Ω(2n)

    C.logn3的渐进表达式上界函数是O(logn)

    D.logn3的渐进表达式下界函数是Ω(n3)

    当输入规模为n时,算法增长率最的是 。

    A.5nB.20log2nC.2n2 D.3nlog3n

    T(n)表示当输入规模为n时,算法的是 。A.T(n)= T(n – 1)+1,T(1)=1 B.T(n)= 2n2

    C.T(n)= T(n/2)+1,T(1)=1 D.T(n)= 3nlog2n

    在棋盘覆盖问题中,对于2k×2k的特殊棋盘(有一个特殊方块),所需的L型骨牌的个数是 。A

    A.(4k – 1)/3 B.2k /3 C.4k D.2k

    在寻找n个元素中第k小元素问题中,若使用快速排序算法思想,运用分治算法对n个元素进行划分,应如何选择划分基准?下面 答案解释最合理。D

    A.随机选择一个元素作为划分基准

    B.取子序列的第一个元素作为划分基准

    C.用中位数的中位数方法寻找划分基准

    D.以上皆可行。但不同方法,算法复杂度上界可能不同

    有9个村庄,其坐标位置如下表所示:

    i123456789x(i)123456789y(i)123456789现在要盖一所邮局为这9个村庄服务,请问邮局应该盖在 才能使到邮局到这9个村庄的总距离和最短。C

    A.(4.5,0)B.(4.5,4.5)C.(5,5)D.(5,0)

    n个人拎着水桶在一个水龙头前面排队打水,水桶有大有小,水桶必须打满水,水流恒定。如下 说法不正确?A

    A.让水桶大的人先打水,可以使得每个人排队时间之和最小

    B.让水桶小的人先打水,可以使得每个人排队时间之和最小

    C.让水桶小的人先打水,在某个确定的时间t内,可以让尽可能多的人打上水

    D.若要在尽可能短的时间内,n个人都打完水,按照什么顺序其实都一样

    分治法的设计思想是将一个难以直接解决的大问题分割成规模较小的子问题,分别解决子问题,最后将子问题的解组合起来形成原问题的解。这要求原问题和子问题 。A.问题规模相同,性质相同B.问题规模相同,性质不同

    C规模不同,性质相同D.问题规模不同,性质不同 是不正确描述。C

    A.布线问题的解空间是一个图

    B.可以对方格阵列四周设置围墙,即增设标记的附加方格的预处理,使得算法简化对边界的判定

    C.采用广度优先的标号法找到从起点到终点的布线方案(这个方案如果存在的话)不一定是最短的

    D.采用先入先出的队列作为活结点表,以终点b为扩展结点或活结点队列为空作为算法结束条件

    对于含有n个元素的子集树问题,最坏情况下其解空间的叶结点数目为 。B

    A.n! B.2n C.2n+1-1 D.

    二、题(0分,每题分)1、一个算法复杂性的高低体现在计算机运行该算法所需的时间和存储器资源上,因此算法的复杂性有 复杂性和复杂性之分。出自于平衡子问题的思想,通常分治法在分割原问题,形成若干子问题时,这些子问题的规模都大致 。3、使用二分搜索算法在n个有序元素表中搜索一个特定元素,在最佳情况下,搜索的时间复杂性为O( ),在最坏情况下,搜索的时间复杂性为O( )。参考解答

    解得此递归方可得T(n)= O( )。参考解答:、动态规划算法有一个变形方法 。这种方法不同于动态规划算法自底向上的填充方向,而是自顶向下的递归方向,为每个解过的子问题建立了备忘录以备需要时查看,同样也可避免相同子问题的重复求解。参考解答、简答题(0分,每题分)

    参考解答:– 1天。

    请利用分治法的思想,给这8位运动员设计一个合理的比赛日程。

    参考解答:

    1234567821436587341278564321876556781234658721437856341287654321

    3、(8分)某体育馆有一羽毛球场出租,现在总共有10位客户申请租用此羽毛球场,每个客户所租用的时间单元如下表所示,s(i)表示开始租用时刻,f(i)表示结束租用时刻,10个客户的申请如下表所示:

    i123456789

    更多相关内容
  • 1、二分搜索算法是利用( A )实现的算法。 A、分治策略 B、动态规划法 C、贪心法 D、回溯法 2、下列不是动态规划算法基本步骤的是( A )。 A、找出最优解的性质 B、构造最优解 C、算出最优解 D、定义最优解 3、...
  • 1二分搜索算法是利用 A 实现的算法 A分治策略 B 动态规划法 C 贪心法 D 回溯法 2下列不是动态规划算法基本步骤的是 A A找出最优解的性质 B 构造最优解 C 算出最优解 D 定义最优解 3最大效益优先是 A 的一搜索方式 A...
  • 天津工业大学《算法设计与分析期末复习题(含答案)
  • 1二分搜索算法是利用 A 实现的算法 A分治策略 B 动态规划法 C 贪心法 D 回溯法 2下列不是动态规划算法基本步骤的是 A A找出最优解的性质 B 构造最优解 C 算出最优解 D 定义最优解 3最大效益优先是 A 的一搜索方式 A...
  • PAGE 1 教育资料 PAGE 1 算法设计与分析历年期末试题整理(含答案) 1用计算机求解问题的步骤 1问题分析 2数学模型建立 3算法设计与选择 4算法指标 5算法分析 6算法实现 7程序调试 8结果整理文档编制 算法定义算法是...
  • 计算机算法设计与分析期末考试复习题知识.pdf
  • 华南农业大学期末考试试卷 A 卷 2007 学年第一学期 考试科目算法分析与设计 考试类型 开卷 考试时间 120 分钟 学号姓名年级专业 题号 一 二 三 总分 得分 评阅人 一选择 20 分每 2 分 1void hanoi(int n, int a,...
  • 算法分析与设计期末复习题 一 选择题 应用Johnson法则的流水作业调度采用的算法是D 贪心算法 B.分支限界法 C.分治法 D.动态规划算法 Hanoi塔问题如下图所示现要求将塔座 A上的的所有圆盘移到塔座 B上并 仍按同样顺序...
  • 算法设计与分析期末考试试题

    热门讨论 2009-01-04 01:01:35
    算法设计与分析 期末考试试题 仅供计算机系学生参考
  • 哈尔滨工业大学《高级算法设计与分析》2019年期末试卷
  • 1.渐进表示法中f(n)= O(g(n))意味着f(n)的数量级 [ 不大于 ] g(n)的数量级【填“小于”、“大于”、“不小于”或“不大于”】,平时各种教材中见到的O(n2)表达的意思是算法的复杂度 [ 等于 ] n2数量级【填“小于...

    1.渐进表示法中f(n)= O(g(n))意味着f(n)的数量级 [ 不大于 ] g(n)的数量级【填“小于”、“大于”、“不小于”或“不大于”】,平时各种教材中见到的O(n2)表达的意思是算法的复杂度
    [ 等于 ] n2数量级【填“小于”、“等于”或“大于”】。
    2.算法的正确性通常采用 【 理论证明 】 或测试的方法。
    3.如果某算法的时间复杂度为θ(2n),机器的运算速度按109次/秒估算,则n= 【30 】时,机器运算时间为1秒钟【注:210≈1000】,如果n增大3,则运算时间会变为 【 8】 秒。
    4.分治算法一般采用 【 二分法 】 。【填“二分法”、“三分法”或“n分法”】
    5.用f(n,m)表示两个长度分别为n,m的字符串X、Y的最长公共子序列的长度,补充完整的递推式。
    0 【 n== 0||m==0 】
    f(n,m)={ f(n-1,m-1)+1 Xn=Ym
    【Max(f(n-1,m),f(n,m-1) 】 Xn != Ym
    6.对于运算量很大的问题,用随机方法其结果通常 【 】误差【填“有”或“没有”】

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

    函数渐进性的O, Ω ,Θ的表示
    在这里插入图片描述

    在这里插入图片描述

    1.如果在这里插入图片描述
    ,则有( B)。 A.
    在这里插入图片描述

    B.
    在这里插入图片描述

    C.
    在这里插入图片描述

    D.以上都不对

    时间复杂度知识点梳理

    2.按数量级排序,正确的是( B )。
    A.n1/2 < (logn)2
    B.n1/2 > (logn)2
    C.logn> n
    D.logn >n1/2

    在这里插入图片描述
    https://blog.csdn.net/qq_40811682/article/details/100052294

    3.对数组元素a[from]~a[to]进行快速排序时,假设一趟相遇过程将元素a[from]移到数组单元a[pos],则初始元素a[from]在该区间是第(C)小元素。
    A.to-from+1 B.from-pos+1 C. pos-from+1 D. to–pos+1

    快速排序

    4.对解空间树进行深度优先搜索的是( A )。
    A.回溯算法 B.分支限界算法 C.分治算法
    D.动态规划算法

    5.硬币找零问题即是对于面值系统为a1,a2,…,ak(其中a1=1)且个数不限的k种硬币,找零S元钱,求最少硬币个数,关于这个问题的描述正确的是(D )。
    A.对于任意面值系统贪心算法均可得到最优解
    B.面值系统必须递减排序,动态规划算法才能得到最优解
    C.贪心算法的时间复杂度是θ(kS)
    D.动态规划算法的时间复杂度是θ(k
    S)

    6.鬼牌除外的一副扑克牌,共有13种扑克牌,每种牌4张,不考虑花色,从中任取k张牌有多少种可能结果?该问题最适合的算法是( C )。
    A.回溯算法
    B.概率算法
    C.动态规划算法
    D.分治算法

    7.如果一个问题采用贪心算法、动态规划算法、回溯算法、分支限界算法都可以得到最优解,对四种算法进行比较,你认为最有可能的是( B )。
    A.动态规划算法效率最高
    B.贪心算法效率最高
    C.回溯算法效率最高
    D.分支限界算法效率最高

    8.下面关于回溯算法与分支限界算法的描述,正确的是( A )。
    A.前者不创建解空间树,后者创建解空间树
    B.后者不创建解空间树,前者创建解空间树
    C.两者均创建解空间树
    D.两者均不创建解空间树

    9.下面关于图论中弗洛伊德算法的描述,错误的是(C )。
    A.能求图中任意两点的最小距离 B.算法可以用二维数组存放结果
    C.算法适合有向图,不能用于无向图 D.图中边的权值必须是非负数

    10.关于P类和NP类问题,下列说法正确的是( A )。
    A.P类是容易处理的
    B.NP类问题是不能处理的
    C.P类=NP类
    D.P类≠NP类
    在这里插入图片描述

    在这里插入图片描述
    三.算法分析题。(本大题4小题,每小题5分,共20分)

    1.分析下面程序段的时间复杂度。

       int i,j,s;
    	for(i=1;i<=n;i++)
    		for(s=0,j=1;s<=n;j++)
           		 s=s+j;
    

    O(N^1.5)

    2.分析下面程序段的时间复杂度。

      int x=n, i=1;
       while(x>0)
    	{  x= x-i; 
    	   i=i*2;
    	}
    

    Log(n+1)=O(logn)

    3.请描述下面递归函数运行时可能发生的问题。

    void f(int n)
    {  int  a[1000];
         if(n>0)  f(n-1);
    }
      int main() { int n=10000;  f(n);  return 0; }
    

    栈内存不够,强制停止递归函数因为栈溢出而被操作系统强制结束

    4.如果机器速度按109次/秒估算,那么下面程序所用时间大约是多少秒?

    void f(int n)
    { 
     if(n<0)  return ;
         else  for(i=1;i<5;i++)  f(n-1);
    }
      int main() { int n=20;  f(n);  return 0; }
    【注:可以按2101000来估算。】
    

    420=240=1000^4,
    10004/109=10^3

    斐波那契数的时间复杂度斐波那契数的时间复杂度、空间复杂度详解在这里插入图片描述

    四.解答题。(本大题3小题,每小题8分,共24分)

    1.如果系统rand( )函数产生的随机数范围在[0,32767],请写出表达式产生[a,b]范围随机整数【其中a,b均为整数,且b-a<32767】,请写出表达式产生[0,1]范围且小数点后含有3位的随机小数。

    rand()%(b-a+1)+a
    Rand()*1001/1000
    在这里插入图片描述

    2.假设打印时间分别为6,3,8,1,4分钟的5个人同时排队等待一台打印机服务,一个人的等待时间=排在他前面的人的打印时间之和+自己的打印时间,为了求出使得所有人的等待时间总和最小的打印顺序,请给出一种贪心策略,并计算出所有人的等待时间之和。

    贪心策略是时间短的先打印,等待时间之和15+34+43+62+8*1=49

    3.分析下面算法程序的输出结果。

     int  n=3,X[100];
       int xianjie(int k, int i)
       {  if(k==1 && i<=2) return 0;
          if(k==2 && i<=1) return 0;
          return 1;
       }
    void  f(int k)
       {  if(k-1==n) { cout<<endl;  for(int i=1;i<=n;i++) cout<<X[i]<<” ”; }
          else  for(int i=1;i<=n;i++)
               if(xianjie(k,i))
               { X[k]=i;  f(k+1);}
       }
       int  main( ){ f(1);  return 0;}
    

    在这里插入图片描述

    五.算法设计题。(本大题2小题,第1小题12分,第2小题14分,共26分)

    1.如图m*n方格矩阵a[m][n]中摆放着价值不等的宝贝(价值可正可负),从左上角a[0][0]出发到达右下角a[m-1][n-1],可以向右或向下走到相邻格子,并捡起当前格子的宝贝(无论价值的正负),每个格子只能走一遍,求能捡到宝贝价值之和的最大值。在这里插入图片描述

    (1)按动态规划算法的解题过程,写出递推关系式。(6分)
    (2)根据递推关系式,写出递归型的动态规划函数。(6分)

    在这里插入图片描述

    在这里插入图片描述

    2.n个正整数元素的集合a[],求元素之和为S的所有子集【注:集合元素依次为a[0],a[1],… a[n-1],要求有剪枝函数】。

    #include<iostream>
    using namespace std;
    int  a[100]= {8,9,7,5,3,2,1} , n=7, S=15;//初始化数据
    

    在这里插入图片描述

    int X[100];
    int sumS=0,leftS=35;
    int xianzhi(int k,int i){
    	if(i==1&&sumS+a[k]>S) return 0;
    	if(i==0&&sumS+leftS-a[k]<S) return 0;
    	return 1;
    }
    void f(int k){
    	if(k-1==n){
    		if(sumS==S){
    			cout<<endl<<"{";
    			for(int i=0;i<=6;i++){
    				if(X[i]==1) 	cout<<a[i]<<", ";
    			}
    			cout<<"}";
    		}
    	}
    	else for(int i=0;i<=1;i++){
    			if(xianzhi(k,i)){
    				X[k]=i;
    				if(i==1){sumS+=a[k];leftS-=a[k];}
    				f(k+1);
    				if(i==1){sumS-=a[k];leftS+=a[k];}
    			}
    	}
    }
    
    int main(){
    	f(0);
    	return 0;
    }
    
    展开全文
  • 重邮计算机算法分析与设计期末考试复习资料总结。
  • 哈尔滨工业大学2020年算法设计与分析考试线上考试真题,仅供复习参考,无标准答案。凑字数凑字数凑字数凑字数凑字数
  • 适用于计算机学院的计算机科学技术专业算法设计与分析练习(计算机科学技术、网络工程、人工智能)
  • 算法设计与分析期末考试 on PTA

    千次阅读 2020-09-03 10:49:31
    算法的复杂性有时间复杂性和空间复杂性之分。 4-2 若存在两个正的常数c和n0,对于任意n≥n0,都有T(n)≤c×f(n),则称T(n)= Ω (f(n))。 4-3 用贪心算法求解的问题一般具有两个重要性质是: 贪心原则和最优子结构...

    4-1
    算法的复杂性有时间复杂性和空间复杂性之分。

    4-2
    若存在两个正的常数c和n0,对于任意n≥n0,都有T(n)≤c×f(n),则称T(n)= Ω (f(n))。

    4-3
    用贪心算法求解的问题一般具有两个重要性质是:
    贪心原则和最优子结构性质。

    4-4
    分支限界法采用
    深度
    优先的方式搜索解空间,回溯法采用
    广度
    优先的方式搜索解空间。

    4-5
    通常,
    贪心算法、分支限界、回溯的求解策略是自顶向下求解,
    动态规划是自底向上的递推求解。

    4-6
    回溯法搜索解空间树时,常用的两种剪枝函数为
    约束函数和限界函数

    4-7
    分支限界法主要有
    队列式 分支限界法和 优先队列式 分支限界法。
    5-1
    如下程序的功能是求解n后问题,请将程序补充完整。(每空2分,共10分)

    #include <iostream.h>
    #include <math.h>
    int n,count,*x;
    void Swap(int& a,int &b){
       int t=a;a=b;b=t; }
    bool Check(int i){    //检查当前第i个皇后的放法是否可行
       for (int k=1;k<i;k++)
           if (
    (a[i]==a[j])||(abs(a[i]-a[j])==i-j)
    )  return false;
        
    else return true
    ;
    }
    void Output(){
        //以表格的形式输出一个解(x1,x2,…,xn),皇后所在的行列位置为“Q”,其它位置输出“_”。
         count++;
         for ( int i=1;i<=n;i++){
             for (j=1;j<=n;j++)
               if (x[i]==j) cout<<" Q";
               else cout<<"_";
             cout<<endl;
         }
     }
    void Queen(int i){
        if  (i>n)Output();
        else 
            for (int j=i;j<=n;j++){
                
    x[i] = j
    ;
                if (check(i))  
    Queen(i+1)Swap(x[i],x[j]);
            }
    }
    void main(){
       cout<<endl<<"Please input n=";   cin>>n;  
       x=new int [n+1];
       for (int i=1;i<=n;i++) 
    x[i]=-1
    ;
       count=0;
       Queen(1);
       cout<<endl<<"Total ="<<count<<endl;
       delete[]x;
    }
    

    7-1 找第k小的数 (20分)
    设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数。

    提示:函数int partition(int a[],int left,int right)的功能是根据a[left]a[right]中的某个元素x(如a[left])对a[left]a[right]进行划分,划分后的x所在位置的左段全小于等于x,右段全大于等于x,同时利用x所在的位置还可以计算出x是这批数据按升非降序排列的第几个数。因此可以编制int find(int a[],int left,int right,int k)函数,通过调用partition函数获得划分点,判断划分点是否第k小,若不是,递归调用find函数继续在左段或右段查找。

    输入格式:
    输入有两行:

    第一行是n和k,0<k<=n<=10000

    第二行是n个整数

    输出格式:
    输出第k小的数

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

    10 4
    2 8 9 0 1 3 6 7 8 2
    输出样例:
    在这里给出相应的输出。例如:

    2

    //找第k小的数 
    #include <iostream> 
    using namespace std;   
    int partition(int a[], int left, int right) {
    //将数组a的第left到right个元素进行划分 	
        int x = a[left]; 	 	
        while (left < right){//采用快排策略 		
            while (left < right && a[right] >= x) right--; 	
            a[left] = a[right]; 		 		
            while (left < right && a[left] <= x) left++; 		
            a[right] = a[left]; 	
        } 	 	
    	a[left] = x; 	 	
    	return left; 
    }   
    int find(int a[], int left, int right, int k) {
    	//在数组a的第left到right中寻找第k小的数 	
    	int pos = partition(a, left, right);   	
    	if (k - 1 == pos) cout << a[k - 1]; 	
    	else if (k - 1 < pos)//判断下一次划分在哪一区间进行 
            find(a, left, pos - 1, k); 	
    	else find(a, pos + 1, right, k);   	
    	return 0;   
    }   
    int main() { 	
        int n, k; 	
    	cin >> n >> k;   	
    	int a[1000]; 	
    	for (int i = 0; i < n; i++) 		
            cin >> a[i];   	
        find(a, 0, n - 1, k);   	
        return 0;   
    }
    

    7-2 装箱问题 (10分)
    假设有N项物品,大小分别为s​1​​ 、s​2​​ 、…、s​i​​ 、…、s​N​​ ,其中s​i​​ 为满足1≤s​i​​ ≤100的整数。要把这些物品装入到容量为100的一批箱子(序号1-N)中。装箱方法是:对每项物品, 顺序扫描箱子,把该物品放入足以能够容下它的第一个箱子中。请写一个程序模拟这种装箱过程,并输出每个物品所在的箱子序号,以及放置全部物品所需的箱子数目。

    输入格式:
    输入第一行给出物品个数N(≤1000);第二行给出N个正整数s​i​​ (1≤s​i​​ ≤100,表示第i项物品的大小)。
    输出格式:
    按照输入顺序输出每个物品的大小及其所在的箱子序号,每个物品占1行,最后一行输出所需的箱子数目。

    输入样例:
    8
    60 70 80 90 30 40 10 20
    输出样例:
    60 1
    70 2
    80 3
    90 4
    30 1
    40 5
    10 1
    20 2
    5

    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main()
    {
        int n,top = 1,i,j,flag;
        int a[1001];
        int b[1001];
        scanf("%d",&n);
        for(i = 0;i < n;i++)
        {
            scanf("%d",&a[i]);
            b[i] = 100;
        }
        if(n == 1)
        {
            printf("%d %d\n%d\n",a[0],top,top);
            return 0;
        }
        for(i = 0;i < n;i++)
        {
            flag = 0;
            for(j = 1;j <= top;j++)
            {
                if(b[j] >= a[i])
                {
                    b[j] -= a[i];
                    flag =1;
                    printf("%d %d\n",a[i],j);
                    break;
                }
            }
            if(!flag)
            {
                top++;
                b[top] -= a[i];
                printf("%d %d\n",a[i],top);
            }
        }
        printf("%d\n",top);
        return 0;
    }
    

    7-3 0-1背包 (20分)
    给定n(n<=100)种物品和一个背包。物品i的重量是wi,价值为vi,背包的容量为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

    #include<iostream>
    using namespace std;
    int main(){
    	int n,c;
    	cin>>n>>c;
    	int w[105];
    	int v[105];
    	int dp[105][1005]={};
    	for(int i=1;cin>>w[i]>>v[i];i++);
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=c;j++){
    			dp[i][j]=dp[i-1][j];
    			if(j>=w[i])
    			dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
    		}
    	}
    	cout<<dp[n][c];
    } 
    

    8-1 算法复杂度分析题 (6分)
    请分别给出你求解7-1、7-2、7-3所设计算法的时空复杂度。
    时间复杂度都为O(n^2)
    8-2 算法应用题 (6分)
    采用启发式搜索A*算法求解以下八数码难题,其中(a)为初始状态,(b)为目标状态,给出求解思路及估价函数。
    在这里插入图片描述

    求解思路:
    对应网址
    用启发式搜索算法求解,A* 算法。
    定义六个结构体
    九宫格的各个数字,
    OPEN结点,
    OPEN表,
    CLOSED结点,
    CLOSED表,
    求解路径。
    自定义函数:
    初始化九宫格;
    判断两个九宫格是否一致;
    求某结点的hx值,即与目标结点九宫格不一样的元素个数;
    对OPEN表按照估价函数值的大小从小到大排序;
    判断某九宫格是否与OPEN表中某结点相同;
    判断某九宫格是否与CLOSED表中某结点相同;
    将一个九宫格中的数字全部复制到另一个九宫格中;
    求OPEN表中某结点的扩展结点;
    删除OPEN表中第一个结点;
    计算估价函数值并赋值;
    以矩阵形式打印九宫格;
    打印求解最终路径;
    启发式搜索函数寻找求解路径。

    估价函数:

    /*********先定义所需要的结构体*********/
    typedef struct{
    int num[3][3];       //九宫格数字
    }Squared;                //九宫格
    ​
    typedef struct{
    Squared stateself;   //九宫格
    int dx;              //结点在搜索树中的深度
    int hx;              //结点对应九宫格与目标九宫格不一样的元素个数
    int fx;              //估价函数fx=dx+hx
    }Open;                   //OPEN结点
    ​
    //求某结点的hx值,即与目标结点九宫格不一样的元素个数
    int GetHx(Squared a,Squared end){
      int count=0;
      for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
          if(a.num[i][j]!=end.num[i][j])
            count++;
        }
      }
      return count;
    }
    ​
    /**********计算估价函数值并赋值**********/
    void CalEvaluate(Open &op,Open pare,Squared end){
      op.dx=pare.dx+1;                 //求dx
      op.hx=GetHx(op.stateself,end);   //求hx
      op.fx=op.dx+op.hx;               //求fx
    }
    

    8-3 最长公共子序列问题(LCS) (16分)
    最长公共子序列问题(LCS) 下面的公式是最长公共序列子问题的递归关系式,Ci,j 表示序列Xi和Yj的最长公共子序列的长度,其中Xi={x1,x2,x3,…,xi},Yj={y1,y2,y3,…,yj}, bi,j 记录了Ci,j 的值是由哪一个子问题的解产生。
    在这里插入图片描述

    已知 X=(a, b, c ,b, d, a, b),Y=(b, d, c, a, b, a) (1)请根据以上动态规划方程给出C表和B表,下表为C表、B表参考格式,请通过上传文件、图片或者插入图片方式提交C表及B表;

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

    (2)根据表C和B的值,X与Y构成的最长公共子序列的长度为多少?
    最大长度为4
    (3)请给出X与Y构成的最长公共子序列?
    公共子序列为bcba

    展开全文
  • 1用计算机求解问题的步骤 法分支限界法 1问题分析 2 数学模型建立 3算 法设计与选择 4 算法指标 5算法分 迭代法 析 6算法实 7程序调试 8结果 基本思想迭代法也称辗转法是 整理文档编制 一种不断用变量的旧值递推出新...
  • 算法设计与分析期末复习题(史上最详细)

    万次阅读 多人点赞 2021-06-07 13:25:06
    算法设计与分析期末复习题(一) 1、二分搜索算法是利用( A )实现的算法。 A、分治策略 B、动态规划法 C、贪心法 D、回溯法 2、下列不是动态规划算法基本步骤的是( A )。 A、找出最优解的性质 B、构造最优解 C、...

    算法设计与分析期末复习题(一)
    1、二分搜索算法是利用( A )实现的算法。
    A、分治策略 B、动态规划法 C、贪心法 D、回溯法
    2、下列不是动态规划算法基本步骤的是( A )。
    A、找出最优解的性质 B、构造最优解 C、算出最优解 D、定义最优解
    3、最大效益优先是( A )的一搜索方式。
    A、分支界限法 B、动态规划法 C、贪心法 D、回溯法
    4、最长公共子序列算法利用的算法是( B )。
    A、分支界限法 B、动态规划法 C、贪心法 D、回溯法
    5. 回溯法解TSP问题时的解空间树是( A )。
    A、子集树 B、排列树 C、深度优先生成树 D、广度优先生成树
    6.下列算法中通常以自底向上的方式求解最优解的是( B )。
    A、备忘录法 B、动态规划法 C、贪心法 D、回溯法
    7、衡量一个算法好坏的标准是(C )。
    A 运行速度快 B 占用空间少 C 时间复杂度低 D 代码短
    8、以下不可以使用分治法求解的是(D )。
    A 棋盘覆盖问题 B 选择问题 C 归并排序 D 0/1背包问题
    9. 实现循环赛日程表利用的算法是( A )。
    A、分治策略 B、动态规划法 C、贪心法 D、回溯法
    10、实现最长公共子序列利用的算法是( B )。
    A、分治策略 B、动态规划法 C、贪心法 D、回溯法
    11.下面不是分支界限法搜索方式的是( D )。
    A、广度优先 B、最小耗费优先 C、最大效益优先 D、深度优先
    12.下列算法中通常以深度优先方式系统搜索问题解的是( D )。
    A、备忘录法 B、动态规划法 C、贪心法 D、回溯法
    13. 一个问题可用动态规划算法或贪心算法求解的关键特征是问题的( B )。
    A、重叠子问题 B、最优子结构性质 C、贪心选择性质 D、定义最优解
    14.广度优先是( A )的一搜索方式。
    A、分支界限法 B、动态规划法 C、贪心法 D、回溯法
    15.背包问题的贪心算法所需的计算时间为( B )。
    A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
    16.实现最大子段和利用的算法是( B )。
    A、分治策略 B、动态规划法 C、贪心法 D、回溯法
    17.实现棋盘覆盖算法利用的算法是( A )。
    A、分治法 B、动态规划法 C、贪心法 D、回溯法
    18.下面是贪心算法的基本要素的是( C )。
    A、重叠子问题 B、构造最优解 C、贪心选择性质 D、定义最优解
    19.回溯法的效率不依赖于下列哪些因素( D )
    A.满足显约束的值的个数 B. 计算约束函数的时间
    C. 计算限界函数的时间 D. 确定解空间的时间
    20.下面哪种函数是回溯法中为避免无效搜索采取的策略( B )
    A.递归函数 B.剪枝函数 C。随机数函数 D.搜索函数
    21、以深度优先方式系统搜索问题解的算法称为 ( D ) 。
    A、分支界限算法 B、概率算法 C、贪心算法 D、回溯算法
    22、贪心算法与动态规划算法的主要区别是( B )。
    A、最优子结构 B、贪心选择性质 C、构造最优解 D、定义最优解
    23. 采用最大效益优先搜索方式的算法是( A )。
    A、分支界限法 B、动态规划法 C、贪心法 D、回溯法
    24. ( D )是贪心算法与动态规划算法的共同点。
    A、重叠子问题 B、构造最优解 C、贪心选择性质 D、最优子结构性质
    25. 矩阵连乘问题的算法可由( B)设计实现。
    A、分支界限算法 B、动态规划算法 C、贪心算法 D、回溯算法
    26. 0-1背包问题的回溯算法所需的计算时间为( A )
    A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
    27、背包问题的贪心算法所需的计算时间为( B )
    A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
    29、使用分治法求解不需要满足的条件是(A )。
    A 子问题必须是一样的 B 子问题不能够重复C 子问题的解可以合并 D 原问题和子问题使用相同的方法解
    30、下面问题(B )不能使用贪心法解决。
    A 单源最短路径问题 B N皇后问题 C 最小花费生成树问题 D 背包问题
    31、下列算法中不能解决0/1背包问题的是(A )
    A 贪心法 B 动态规划 C 回溯法 D 分支限界法
    32、回溯法搜索状态空间树是按照(C )的顺序。
    A 中序遍历 B 广度优先遍历 C 深度优先遍历 D 层次优先遍历
    33、采用广度优先策略搜索的算法是( A )。
    A、分支界限法 B、动态规划法 C、贪心法 D、回溯法
    34.实现合并排序利用的算法是( A )。
    A、分治策略 B、动态规划法 C、贪心法 D、回溯法
    35.下列是动态规划算法基本要素的是( D )。
    A、定义最优解 B、构造最优解 C、算出最优解 D、子问题重叠性质
    36.下列算法中通常以自底向下的方式求解最优解的是( B )。
    A、分治法 B、动态规划法 C、贪心法 D、回溯法
    二、 填空题
    1.算法的复杂性有 时间 复杂性和 空间 复杂性之分。
    2、程序是 算法 用某种程序设计语言的具体实现。
    3、算法的“确定性”指的是组成算法的每条 指令 是清晰的,无歧义的。
    4.矩阵连乘问题的算法可由 动态规划 设计实现。
    5、算法是指解决问题的 一种方法 或 一个过程 。
    6、快速排序算法的性能取决于 划分的对称性 。
    7、从分治法的一般设计模式可以看出,用它设计出的程序一般是 递归算法 。
    8、问题的 最优子结构性质 是该问题可用动态规划算法或贪心算法求解的关键特征。
    9、以深度优先方式系统搜索问题解的算法称为 回溯法 。
    10、任何可用计算机求解的问题所需的时间都与其 规模 有关。
    11、计算一个算法时间复杂度通常可以计算 循环次数 、 基本操作的频率 或计算步。
    12、回溯法搜索解空间树时,常用的两种剪枝函数为 约束函数 和 限界函数
    14、解决0/1背包问题可以使用动态规划、回溯法和分支限界法,其中不需要排序的是 动态规划 ,需要排序的是 回溯法 ,分支限界法 。
    15、使用回溯法进行状态空间树裁剪分支时一般有两个标准:约束条件和目标函数的界,N皇后问题和0/1背包问题正好是两种不同的类型,其中同时使用约束条件和目标函数的界进行裁剪的是 0/1背包问题 ,只使用约束条件进行裁剪的是 N皇后问题 。
    17、回溯法是一种既带有 系统性 又带有 跳跃性 的搜索算法。
    18. 动态规划算法的两个基本要素是. 最优子结构性质和 重叠子问题 性质
    19.贪心算法的基本要素是 贪心选择 质和 最优子结构 性质 。
    21. 动态规划算法的基本思想是将待求解问题分解成若干 子问题 ,先求解 子问题 ,然后从这些 子问题 的解得到原问题的解。
    算法是由若干条指令组成的有穷序列,且要满足输入,输出 、确定性和 有限性 四条性质。
    23、快速排序算法是基于 分治策略 的一种排序算法。
    24、以广度优先或以最小耗费方式搜索问题解的算法称为 分支限界法 。
    三、算法设计题
    1.背包问题的贪心算法, 分支限界算法
    2.最大子段和: 动态规划算法
    3.贪心算法求活动安排问题
    5.快速排序
    6. 多机调度问题-贪心算法

    四、简答题
    1分治法的基本思想
    2. 分治法与动态规划法的相同点
    3. 分治法与动态规划法的不同点
    4. 分支限界法与回溯法的相同点
    5.分治法所能解决的问题一般具有的几个特征是:
    6. 用分支限界法设计算法的步骤
    7. 回溯法中常见的两类典型的解空间树是子集
    8. 请简述符号t(n)∈θ(g(n)), t(n)∈Ω(g(n)),t(n)∈Ο(g(n))的含义。
    9. 分支限界法的搜索策略是:
    算法设计与分析期末复习题(二)

    蒈一、选择题(20分)

    薆1.最长公共子序列算法利用的算法是(???B???)。

    莆A、分支界限法 B、动态规划法 C、贪心法 D、回溯法

    膄2.实现棋盘覆盖算法利用的算法是(???A???)。

    蒁A、分治法 B、动态规划法 C、贪心法 D、回溯法

    薆3.下面是贪心算法的基本要素的是(???C???)。

    薃A、重叠子问题 B、构造最优解 C、贪心选择性质 D、定义最优解

    蚂4.回溯法的效率不依赖于下列哪些因素(D)

    芀A.满足显约束的值的个数 B.计算约束函数的时间

    蚆C.计算限界函数的时间 D.确定解空间的时间

    羄5.下面哪种函数是回溯法中为避免无效搜索采取的策略(???B???)

    莄A.递归函数 B.剪枝函数 C。随机数函数 D.搜索函数

    罿6.采用最大效益优先搜索方式的算法是(???A???)。

    聿A、分支界限法 B、动态规划法 C、贪心法 D、回溯法

    莅7.贪心算法与动态规划算法的主要区别是(??B???)。

    螂A、最优子结构 B、贪心选择性质 C、构造最优解 D、定义最优解

    肂8.实现最大子段和利用的算法是(???B???)。

    腿A、分治策略 B、动态规划法 C、贪心法 D、回溯法

    螆9.优先队列式分支限界法选取扩展结点的原则是(???C???)。

    薄A、先进先出 B、后进先出 C、结点的优先级 D、随机

    螁10.下列算法中通常以广度优先方式系统搜索问题解的是(???A??)。

    艿A、分支限界法 B、动态规划法 C、贪心法 D、回溯法

    膇二、填空题(22分每空2分)

    羂1.算法是由若干条指令组成的有穷序列,且要满足输入、输出、确定性和有限性四条性质。

    薀2、大整数乘积算法是用分治法来设计的。

    艿3、以广度优先或以最小耗费方式搜索问题解的算法称为分支限界法。

    芄4、舍伍德算法总能求得问题的一个解。

    蚄5、贪心选择性质是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。

    荿6.快速排序

    荿template

    蚅voidQuickSort(Typea[],intp,intr)

    膁{

    莁if(p<r){

    葿intq=Partition(a,p,r);

    肅QuickSort(a,p,q-1);//对左半段排序

    袃QuickSort(a,q+1,r);//对右半段排序

    膀}

    蕿}

    蒆7.哈密顿环问题的算法可由回溯法设计实现。

    芁8.贪心算法不一定产生最优解。

    衿9.算法中通常以深度优先方式系统搜索问题解的是回溯法。

    虿三、算法设计与分析(25分)

    蚃1.用欧几里德迭代算法求两个数的最小公倍数(10分)

    莃#include

    羈usingnamespacestd;

    聿intGcd(intm,intn)

    莄{

    螁 if(m==0)

    肁 returnn;

    腿 if(n==0)

    螅 returnm;

    薃 intt=m>n?n:m;

    螀 while(m%t||n%t)

    艿 t–;

    膆 returnt;

    羁}

    蕿intmain()

    芈{

    薇 inta,b;

    蚃 cout<<“Inputa&b(0<=a<b):”;

    薂 cin>>a>>b;

    莈 intm=a*b/Gcd(a,b);

    蚄 cout<<“TheLeastCommonMultipleis:”<<m<<endl;

    蒅 return0;

    莁2、试用动态规划算法实现最大子矩阵和问题:求矩阵A的一个子矩阵,使其各元素之各为最大。(15分)

    蒈解:解答如下:

    肅intMaxSum2(intm,intn,int**a)

    袃{

    膀intsum=0;

    薈int*b=newint[n+1];

    蒆for(inti=1;i<=m;i++){

    薄for(intk=1;k<=n;k++)b[k]=0;………………………………(5分)

    罿for(intj=i;j<=m;j++){

    羂for(intk=1;k<=n;k++)b[k]+=a[j][k];

    膁intmax=MaxSum(n,b);

    芆if(max>sum)sum=max;

    芅}

    羂}

    芇returnsum;………………………………(10分)

    肈}

    羄intMaxSum(intn,int*a)

    肂{

    蚈intsum=0,b=0;

    蒆for(inti=1;i<=n;i++){

    螃if(b>0)b+=a[i];

    膂elseb=a[i];

    聿if(b>sum)sum=b;

    膈}

    螆Returnsum;………………………………(15分)

    芁}

    薀四、简答题(33分)

    蚆1、假设有7个物品,它们的重量和价值如下表所示。若这些物品均可以被分割,且背包容量M=150,如果使用贪心方法求解此背包问题,使收益最大,请写出求解过程请写出求解过程。(10分)

    薅物品
    莁A
    羁B
    莈C
    莄D
    蒁E
    肈F
    袆G

    肃重量
    薁35
    葿30
    薈60
    膆50
    薁40
    袀10
    羅25

    袄价值
    蚁10
    芀40
    蚇30
    蚃50
    螁35
    蚁40
    膅30

    蚆解:使用单位价值从大到小:FBGDECA,得到贪心解为:FBGD全部放入,而E放入87.5%,得到价值为190.625。

    袁2.写出分治算法MaxMin算法对下列实例中找最大数和最小数的过程。(10分)

    螈数组A=(48,12,61,3,5,19,32,7)

    袇解:1、48,12,61,3,5,19,32,7表中元素多于二,对半分割

    蒅2、48,1261,35,1932,7表中元素多于二,对半分割

    羀3、48~61,12~319~32,5~7

    腿求前半部分的最大最小和后半部分的最大最小,两个半部分的大者为最大,小者为最小

    蕿4、61~323~5两个半部分的大者为最大,小者为最小

    芄5、613寻找结束

    肀3.写出多段图最短路经动态规划算法求解下列实例的过程,并求出最优值。(13分)

    膀484

    腿3

    羆545
    2
    216

    各边的代价如下:
    C(1,2)=3,C(1,3)=5,C(1,4)=2
    C(2,6)=8,C(2,7)=4,C(3,5)=5,C(3,6)=4,C(4,5)=2,C(4,6)=1
    C(5,8)=4,C(6,8)=5,C(7,8)=6
    解:Cost(4,8)=0
    Cost(3,7)=C(7,8)+0=6,
    Cost(3,6)=C(6,8)+0=5,
    Cost(3,5)=C(5,8)+0=4
    Cost(2,4)=min{C(4,6)+Cost(3,6),C(4,5)+Cost(3,5)}
    =min{1+5,2+4}=6
    Cost(2,3)=min{C(3,6)+Cost(3,6)}
    =min{4+5}=9
    Cost(2,2)=min{C(2,6)+Cost(3,6),C(2,7)+Cost(3,7)}
    =min{8+5,4+6}=10
    Cost(1,1)=min{C(1,2)+Cost(2,2),C(1,3)+Cost(2,3),C(1,4)+Cost(2,4)}
    =min{3+10,5+9,2+6}=8
    按上所述,Cost(1,1)为所求最优值。
    算法设计与分析期末复习题(三)
    1
    《算法设计与分析》历年期末试题整理(含答案) (1)用计算机求解问题的步骤:
    1、问题分析 2、数学模型建立 3、算法设计与选择 4、算法指标 5、算法分析 6、算法实现 7、
    程序调试 8、结果整理文档编制
    (2)算法定义:算法是指在解决问题时,按照某种机械步骤一定可以得到问题结果的处理
    过程
    (3)算法的三要素
    1、操作 2、控制结构 3、数据结构
    算法具有以下 5 个属性:
    有穷性:一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成。
    确定性:算法中每一条指令必须有确切的含义。不存在二义性。只有一个入口和一个出

    可行性:一个算法是可行的就是算法描述的操作是可以通过已经实现的基本运算执行有
    限次来实现的。
    输入:一个算法有零个或多个输入,这些输入取自于某个特定对象的集合。
    输出:一个算法有一个或多个输出,这些输出同输入有着某些特定关系的量。
    算法设计的质量指标:
    正确性:算法应满足具体问题的需求;
    可读性:算法应该好读,以有利于读者对程序的理解;
    健壮性:算法应具有容错处理,当输入为非法数据时,算法应对其作出反应,而不是产
    生莫名其妙的输出结果。
    效率与存储量需求:效率指的是算法执行的时间;存储量需求指算法执行过程中所需要
    的最大存储空间。一般这两者与问题的规模有关。
    经常采用的算法主要有迭代法、分而治之法、贪婪法、动态规划法、回溯法、分支限界法
    迭代法 也称“辗转法”,是一种不断用变量的旧值递推出新值的解决问题的方
    法。
    利用迭代算法解决问题,需要做好以下三个方面的工作:
    一、确定迭代模型。在可以用迭代算法解决的问题中,至少存在一个直接或
    间接地不断由旧值递推出新值的变量,这个变量就是迭代变量。
    二、建立迭代关系式。所谓迭代关系式,指如何从变量的前一个值推出其下
    一个值的公式(或关系)。迭代关系式的建立是解决迭代问题的关键,通常可以
    使用递推或倒推的方法来完成。
    三、对迭代过程进行控制。在什么时候结束迭代过程?这是编写迭代程序必
    须考虑的问题。不能让迭代过程无休止地重复执行下去。迭代过程的控制通常可
    分为两种情况:一种是所需的迭代次数是个确定的值,可以计算出来;另一种是
    所需的迭代次数无法确定。对于前一种情况,可以构建一个固定次数的循环来实
    现对迭代过程的控制;对于后一种情况,需要进一步分析出用来结束迭代过程的
    条件。
    编写计算斐波那契(Fibonacci)数列的第 n 项函数 fib(n)。
    斐波那契数列为:0、1、1、2、3、……,即:
    2
    fib(0)=0;
    fib(1)=1;
    fib(n)=fib(n-1)+fib(n-2) (当 n>1 时)。
    写成递归函数有:
    int fib(int n)
    { if (n0) return 0;
    if (n
    1) return 1;
    if (n>1) return fib(n-1)+fib(n-2);
    }
    一个饲养场引进一只刚出生的新品种兔子,这种兔子从出生的下一个月开始,
    每月新生一只兔子,新生的兔子也如此繁殖。如果所有的兔子都不死去,问到
    第 12 个月时,该饲养场共有兔子多少只?
    分析: 这是一个典型的递推问题。我们不妨假设第 1 个月时兔子的只数为
    u 1 ,第 2 个月时兔子的只数为 u 2 ,第 3 个月时兔子的只数为 u 3 ,……
    根据题意,“这种兔子从出生的下一个月开始,每月新生一只兔子”,则有
    u 1 = 1 , u 2 = u 1 + u 1 × 1 = 2 , u 3 = u 2 + u 2 × 1 =
    4 ,……

    根据这个规律,可以归纳出下面的递
    推公式:
    u n = u n - 1 × 2 (n ≥ 2)
    对应 u n 和 u n - 1 ,定义两
    个迭代变量 y 和 x ,可将上面的递
    推公式转换成如下迭代关系:
    y=x2
    x=y
    让计算机对这个迭代关系重复执
    行 11 次,就可以算出第 12 个月时
    的兔子数。参考程序如下:
    cls
    x=1
    for i=2 to 12
    y=x
    2
    x=y
    next i
    print y
    end
    分而治之法
    1、分治法的基本思想
    任何一个可以用计算机求解的问题所需的计算时间都与其规模 N 有关。问题
    的规模越小,越容易直接求解,解题所需的计算时间也越少。例如,对于 n 个元素的
    排序问题,当 n=1 时,不需任何计算;n=2 时,只要作一次比较即可排好序;n=3 时
    只要作 3 次比较即可,…。而当 n 较大时,问题就不那么容易处理了。要想直接解决
    一个规模较大的问题,有时是相当困难的。
    分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的
    相同问题,以便各个击破,分而治之。
    分治法所能解决的问题一般具有以下几个特征:
    (1)该问题的规模缩小到一定的程度就可以容易地解决;
    3
    (2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结
    构性质;
    (3)利用该问题分解出的子问题的解可以合并为该问题的解;
    (4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共
    的子子问题。
    3、分治法的基本步骤
    分治法在每一层递归上都有三个步骤:
    (1)分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同
    的子问题;
    (2)解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子
    问题;
    (3)合并:将各个子问题的解合并为原问题的解。
    快速排序
    在这种方法中, n 个元素被分成三段(组):左段 l e f t,右段 r i g h t 和中段 m i d d l e。中
    段仅包含一个元素。左段中各元素都小于等于中段元素,右段中各元素都大于等于中段元素。
    因此 l e f t 和 r i g h t 中的元素可以独立排序,并且不必对 l e f t 和 r i g h t 的排序结果进行合
    并。m i d d l e 中的元素被称为支点( p i v o t )。图 1 4 - 9 中给出了快速排序的伪代码。
    / /使用快速排序方法对 a[ 0 :n- 1 ]排序
    从 a[ 0 :n- 1 ]中选择一个元素作为 m i d d l e,该元素为支点
    把余下的元素分割为两段 left 和 r i g h t,使得 l e f t 中的元素都小于等于支点,而 right
    中的元素都大于等于支点
    递归地使用快速排序方法对 left 进行排序
    递归地使用快速排序方法对 right 进行排序
    所得结果为 l e f t + m i d d l e + r i g h t
    考察元素序列[ 4 , 8 , 3 , 7 , 1 , 5 , 6 , 2 ]。假设选择元素 6 作为支点,则 6 位于 m i d d l e; 4,3,1,5,2 位于 l e f t;8,7 位于 r i g h t。当 left 排好序后,所得结果为 1,2,3,4, 5;当 r i g h t 排好序后,所得结果为 7,8。把 right 中的元素放在支点元素之后, l e f t 中
    的元素放在支点元素之前,即可得到最终的结果[ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ]。
    把元素序列划分为 l e f t、m i d d l e 和 r i g h t 可以就地进行(见程序 1 4 - 6)。在程序
    1 4 - 6 中,支点总是取位置 1 中的元素。也可以采用其他选择方式来提高排序性能,本章稍
    后部分将给出这样一种选择。
    程序 14-6 快速排序

    template
    void QuickSort(T*a, int n)
    {// 对 a[0:n-1] 进行快速排序
    {// 要求 a[n] 必需有最大关键值
    quickSort(a, 0, n-1);
    template
    void quickSort(T a[], int l, int r)
    {// 排序 a [ l : r ], a[r+1] 有大值
    if (l >= r) return;
    int i = l, // 从左至右的游标
    j = r + 1; // 从右到左的游标
    T pivot = a[l];
    // 把左侧>= pivot 的元素与右侧<=
    pivot 的元素进行交换
    while (true) {
    do {// 在左侧寻找>= pivot 的元素
    i = i + 1;
    } while (a < pivot);
    do {// 在右侧寻找<= pivot 的元素
    j = j - 1;
    } while (a[j] > pivot);
    if (i >= j) break; // 未发现交换对象
    4
    Swap(a, a[j]);
    }
    // 设置 p i v o t
    a[l] = a[j];
    a[j] = pivot;
    quickSort(a, l, j-1); // 对左段排序
    quickSort(a, j+1, r); // 对右段排序
    }
    贪婪法
    它采用逐步构造最优解的思想,在问题求解的每一个阶段,都作出一个在一 定标准下看上
    去最优的决策;决策一旦作出,就不可再更改。制定决策的依据称为贪婪准则。
    贪婪法是一种不追求最优解,只希望得到较为满意解的方法。贪婪法一般可以快速得到
    满意的解,因为它省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪婪法常以当
    前情况为基础作最优选择,而不考虑各种可能的整体情况,所以贪婪法不要回溯。
    【问题】 背包问题
    问题描述:有不同价值、不同重量的物品 n 件,求从这 n 件物品中选取一部分物品的选择方案,使
    选中物品的总重量不超过指定的限制重量,但选中物品的价值之和最大。

    #include<stdio.h>
    void main()
    {
    int
    m,n,i,j,w[50],p[50],pl[50],b[50],s=0,max;
    printf(“输入背包容量 m,物品种类 n :”);
    scanf("%d %d",&m,&n);
    for(i=1;i<=n;i=i+1)
    {
    printf(“输入物品的重量 W 和价值
    P :”);
    scanf("%d %d",&w[i],&p[i]);
    pl[i]=p[i];
    s=s+w[i];
    }
    if(s<=m)
    {
    printf(“whole choose\n”);
    //return;
    }
    for(i=1;i<=n;i=i+1)
    {
    max=1;
    for(j=2;j<=n;j=j+1)
    if(pl[j]/w[j]>pl[max]/w[max])
    max=j;
    pl[max]=0;
    b[i]=max;
    }
    for(i=1,s=0;s<m && i<=n;i=i+1)
    s=s+w[b[i]];
    if(s!=m)
    w[b[i-1]]=m-w[b[i-1]];
    for(j=1;j<=i-1;j=j+1)
    printf(“choose weight %d\n”,w[b[j]]);
    }动态规划的基本思想
    前文主要介绍了动态规划的一些理论依据,我们将前文所说的具有明显的阶段划分和状态转
    移方程的动态规划称为标准动态规划,这种标准动态规划是在研究多阶段决策问题时推导出
    来的,具有严格的数学形式,适合用于理论上的分析。在实际应用中,许多问题的阶段划分
    并不明显,这时如果刻意地划分阶段法反而麻烦。一般来说,只要该问题可以划分成规模更
    小的子问题,并且原问题的最优解中包含了子问题的最优解(即满足最优子化原理),则可
    以考虑用动态规划解决。
    5
    动态规划的实质是分治思想和解决冗余,因此,动态规划是一种将问题实例分解为更小的、
    相似的子问题,并存储子问题的解而避免计算重复的子问题,以解决最优化问题的算法策略。
    由此可知,动态规划法与分治法和贪心法类似,它们都是将问题实例归纳为更小的、相似的
    子问题,并通过求解子问题产生一个全局最优解。
    贪心法的当前选择可能要依赖已经作出的所有选择,但不依赖于有待于做出的选择和子问
    题。因此贪心法自顶向下,一步一步地作出贪心选择;
    而分治法中的各个子问题是独立的(即不包含公共的子问题),因此一旦递归地求出各子问
    题的解后,便可自下而上地将子问题的解合并成问题的解。
    不足之处:如果当前选择可能要依赖子问题的解时,则难以通过局部的贪心策略达到全局最
    优解;如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题。
    解决上述问题的办法是利用动态规划。该方法主要应用于最优化问题,这类问题会有多种可
    能的解,每个解都有一个值,而动态规划找出其中最优(最大或最小)值的解。若存在若干
    个取最优值的解的话,它只取其中的一个。在求解过程中,该方法也是通过求解局部子问题
    的解达到全局最优解,但与分治法和贪心法不同的是,动态规划允许这些子问题不独立,(亦
    即各子问题可包含公共的子问题)也允许其通过自身子问题的解作出选择,该方法对每一个
    子问题只解一次,并将结果保存起来,避免每次碰到时都要重复计算。
    因此,动态规划法所针对的问题有一个显著的特征,即它所对应的子问题树中的子问题呈现
    大量的重复。动态规划法的关键就在于,对于重复出现的子问题,只在第一次遇到时加以求
    解,并把答案保存起来,让以后再遇到时直接引用,不必重新求解。
    3、动态规划算法的基本步骤
    设计一个标准的动态规划算法,通常可按以下几个步骤进行:
    (1)划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。注意这若干个阶段
    一定要是有序的或者是可排序的(即无后向性),否则问题就无法用动态规划求解。
    (2)选择状态:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。
    当然,状态的选择要满足无后效性。
    (3)确定决策并写出状态转移方程:之所以把这两步放在一起,是因为决策和状态转移有
    着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以,如果
    我们确定了决策,状态转移方程也就写出来了。但事实上,我们常常是反过来做,根据相邻
    两段的各状态之间的关系来确定决策。
    (4)写出规划方程(包括边界条件):动态规划的基本方程是规划方程的通用形式化表达式。
    一般说来,只要阶段、状态、决策和状态转移确定了,这一步还是比较简单的。动态规划的
    主要难点在于理论上的设计,一旦设计完成,实现部分就会非常简单。根据动态规划的基本
    方程可以直接递归计算最优值,但是一般将其改为递推计算,实现的大体上的框架如下:
    标准动态规划的基本框架

    1. 对fn+1(xn+1)初始化; {边界条件}
      for k:=n downto 1 do
      for 每一个xk∈Xk do
      for 每一个uk∈Uk(xk) do
      begin
      fk(xk):=一个极值; {∞或-∞} xk+1:=Tk(xk,uk); {状态转移方程}
      t:=φ(fk+1(xk+1),vk(xk,uk)); {基本方程(9)式}
      if t比fk(xk)更优 then fk(xk):=t; {计算fk(xk)的最优值}
      end;
      6
      t:=一个极值; {∞或-∞}
      for 每一个x1∈X1 do
      if f1(x1)比t更优 then t:=f1(x1); {按照 10 式求出最优指标}
      输出 t;
      但是,实际应用当中经常不显式地按照上面步骤设计动态规划,而是按以下几个步骤进行:
      (1)分析最优解的性质,并刻划其结构特征。
      (2)递归地定义最优值。
      (3)以自底向上的方式或自顶向下的记忆化方法(备忘录法)计算出最优值。
      (4)根据计算最优值时得到的信息,构造一个最优解。
      步骤(1)~(3)是动态规划算法的基本步骤。在只需要求出最优值的情形,步骤(4)可
      以省略,若需要求出问题的一个最优解,则必须执行步骤(4)。此时,在步骤(3)中计算
      最优值时,通常需记录更多的信息,以便在步骤(4)中,根据所记录的信息,快速地构造
      出一个最优解。
      总结:动态规划实际上就是最优化的问题,是指将原问题的大实例等价于同一最优化问题的
      较小实例,自底向上的求解最小实例,并将所求解存放起来,存放的结果就是为了准备数据。
      与递归相比,递归是不断的调用子程序求解,是自顶向下的调用和求解。
      回溯法
      回溯法也称为试探法,该方法首先暂时放弃关于问题规模大小的限制,并将问题的候选
      解按某种顺序逐一枚举和检验。当发现当前候选解不可能是解时,就选择下一个候选解;倘
      若当前候选解除了还不满足问题规模要求外,满足所有其他要求时,继续扩大当前候选解的
      规模,并继续试探。如果当前候选解满足包括问题规模在内的所有要求时,该候选解就是问
      题的一个解。在回溯法中,放弃当前候选解,寻找下一个候选解的过程称为回溯。扩大当前
      候选解的规模,以继续试探的过程称为向前试探。
      1、回溯法的一般描述
      可用回溯法求解的问题P,通常要能表达为:对于已知的由n元组(x1,x2,…,xn)组成的
      一个状态空间E={(x1,x2,…,xn)∣xi∈Si ,i=1,2,…,n},给定关于n元组中的一个
      分量的一个约束集D,要求E中满足D的全部约束条件的所有n元组。其中Si是分量xi的定义
      域,且 |Si| 有限,i=1,2,…,n。我们称E中满足D的全部约束条件的任一n元组为问题P
      的一个解。
      解问题 P 的最朴素的方法就是枚举法,即对 E 中的所有 n 元组逐一地检测其是否满足 D 的
      全部约束,若满足,则为问题 P 的一个解。但显然,其计算量是相当大的。
      我们发现,对于许多问题,所给定的约束集D具有完备性,即i元组(x1,x2,…,xi)满足
      D中仅涉及到x1,x2,…,xi的所有约束意味着j(j<i)元组(x1,x2,…,xj)一定也满足
      D中仅涉及到x1,x2,…,xj的所有约束,i=1,2,…,n。换句话说,只要存在 0≤j≤n-1,
      使得(x1,x2,…,xj)违反D中仅涉及到x1,x2,…,xj的约束之一,则以(x1,x2,…,
      xj)为前缀的任何n元组(x1,x2,…,xj,xj+1,…,xn)一定也违反D中仅涉及到x1,x2,…,
      xi的一个约束,n≥i>j。因此,对于约束集D具有完备性的问题P,一旦检测断定某个j元组(x1, x2,…,xj)违反D中仅涉及x1,x2,…,xj的一个约束,就可以肯定,以(x1,x2,…,xj)
      为前缀的任何n元组(x1,x2,…,xj,xj+1,…,xn)都不会是问题P的解,因而就不必去
      搜索它们、检测它们。回溯法正是针对这类问题,利用这类问题的上述性质而提出来的比枚
      举法效率更高的算法。
      回溯法首先将问题 P 的 n 元组的状态空间 E 表示成一棵高为 n 的带权有序树 T,把在 E 中
      求问题 P 的所有解转化为在 T 中搜索问题 P 的所有解。树 T 类似于检索树,它可以这样构
      7
      造:
      设Si中的元素可排成xi
      (1) ,xi
      (2) ,…,xi
      (mi-1) ,|Si| =mi,i=1,2,…,n。从根开始,
      让T的第I层的每一个结点都有mi个儿子。这mi个儿子到它们的双亲的边,按从左到右的次
      序,分别带权xi+1
      (1) ,xi+1
      (2) ,…,xi+1
      (mi) ,i=0,1,2,…,n-1。照这种构造方式,E中的
      一个n元组(x1,x2,…,xn)对应于T中的一个叶子结点,T的根到这个叶子结点的路径上
      依次的n条边的权分别为x1,x2,…,xn,反之亦然。另外,对于任意的 0≤i≤n-1,E中n
      元组(x1,x2,…,xn)的一个前缀I元组(x1,x2,…,xi)对应于T中的一个非叶子结点,
      T的根到这个非叶子结点的路径上依次的I条边的权分别为x1,x2,…,xi,反之亦然。特别,
      E中的任意一个n元组的空前缀(),对应于T的根。
      因而,在E中寻找问题P的一个解等价于在T中搜索一个叶子结点,要求从T的根到该叶
      子结点的路径上依次的n条边相应带的n个权x1,x2,…,xn满足约束集D的全部约束。在T
      中搜索所要求的叶子结点,很自然的一种方式是从根出发,按深度优先的策略逐步深入,即
      依次搜索满足约束条件的前缀 1 元组(x1i)、前缀 2 元组(x1,x2)、…,前缀I元组(x1, x2,…,xi),…,直到i=n为止。
      在回溯法中,上述引入的树被称为问题 P 的状态空间树;树 T 上任意一个结点被称为问
      题 P 的状态结点;树 T 上的任意一个叶子结点被称为问题 P 的一个解状态结点;树 T 上满
      足约束集 D 的全部约束的任意一个叶子结点被称为问题 P 的一个回答状态结点,它对应于
      问题 P 的一个解。
      【问题】 n 皇后问题
      问题描述:求出在一个 n×n 的棋盘上,放置 n 个不能互相捕捉的国际象棋“皇后”
      的所有布局。

    这是来源于国际象棋的一个问题。皇后可以沿着纵横和两条斜线 4 个方向相互捕捉。
    如图所示,一个皇后放在棋盘的第 4 行第 3 列位置上,则棋盘上凡打“×”的位置上的皇后
    就能与这个皇后相互捕捉。

    1 2 3 4 5 6 7 8
    × ×
    × × ×
    × × ×
    × × Q × × × × ×
    × × ×
    × × ×
    × ×
    × ×
    从图中可以得到以下启示:一个合适的解应是在每列、每行上只有一个皇后,且一条
    斜线上也只有一个皇后。

    求解过程从空配置开始。在第 1 列至第 m 列为合理配置的基础上,再配置第 m+1 列,
    直至第 n 列配置也是合理时,就找到了一个解。接着改变第 n 列配置,希望获得下一个解。
    另外,在任一列上,可能有 n 种配置。开始时配置在第 1 行,以后改变时,顺次选择第 2
    行、第 3 行、…、直到第 n 行。当第 n 行配置也找不到一个合理的配置时,就要回溯,去改
    变前一列的配置。得到求解皇后问题的算法如下:
    8
    { 输入棋盘大小值 n;
    m=0;
    good=1;
    do {
    if (good)
    if (m==n)
    { 输出解;
    改变之,形成下一个候选解;
    }
    else 扩展当前候选接至下一列;
    else 改变之,形成下一个候选解;
    good=检查当前候选解的合理性;
    } while (m!=0);
    }

    在编写程序之前,先确定边式棋盘的数据结构。比较直观的方法是采用一个二维数组,
    但仔细观察就会发现,这种表示方法给调整候选解及检查其合理性带来困难。更好的方法乃
    是尽可能直接表示那些常用的信息。对于本题来说,“常用信息”并不是皇后的具体位置,
    而是“一个皇后是否已经在某行和某条斜线合理地安置好了”。因在某一列上恰好放一个皇
    后,引入一个一维数组(col[
    ]),值 col[i]表示在棋盘第 i 列、col[i]行有一个皇后。例如:col[3]=4,就表示在棋盘
    的第 3 列、第 4 行上有一个皇后。另外,为了使程序在找完了全部解后回溯到最初位置,设
    定 col[0]的初值为 0 当回溯到第 0 列时,说明程序已求得全部解,结束程序运行。
    为使程序在检查皇后配置的合理性方面简易方便,引入以下三个工作数组:
    (1) 数组 a[ ],a[k]表示第 k 行上还没有皇后;
    (2) 数组 b[ ],b[k]表示第 k 列右高左低斜线上没有皇后;
    (3) 数组 c[ ],c[k]表示第 k 列左高右低斜线上没有皇后;
    棋盘中同一右高左低斜线上的方格,他们的行号与列号之和相同;同一左高右低斜线
    上的方格,他们的行号与列号之差均相同。

    初始时,所有行和斜线上均没有皇后,从第 1 列的第 1 行配置第一个皇后开始,在第
    m 列 col[m]行放置了一个合理的皇后后,准备考察第 m+1 列时,在数组 a[
    ]、b[ ]和 c[ ]中为第 m 列,col[m]行的位置设定有皇后标志;当从第 m 列回溯到第
    m-1 列,并准备调整第 m-1 列的皇后配置时,清除在数组 a[
    ]、b[ ]和 c[ ]中设置的关于第 m-1 列,col[m-1]行有皇后的标志。一个皇后在 m 列,
    col[m]行方格内配置是合理的,由数组 a[ ]、b[ ]和 c[ ]对应位置的值都为 1 来确定。细节见
    以下程序:
    【程序】

    include

    include

    define MAXN 20

    int n,m,good;
    9
    int col[MAXN+1],a[MAXN+1],b[2MAXN+1],c[2MAXN+1];
    void main()
    { int j;
    char awn;
    printf(“Enter n: “); scanf(“%d”,&n);
    for (j=0;j<=n;j++) a[j]=1;
    for (j=0;j<=2*n;j++) cb[j]=c[j]=1;
    m=1; col[1]=1; good=1; col[0]=0;
    do {
    if (good)
    if (mn)
    { printf(“列\t 行”);
    for (j=1;j<=n;j++)
    printf(“%3d\t%d\n”,j,col[j]);
    printf(“Enter a character (Q/q for exit)!\n”);
    scanf(“%c”,&awn);
    if (awn
    ’Q’||awn==’q’) exit(0);
    while (col[m]==n)
    { m–;
    a[col[m]]=b[m+col[m]]=c[n+m-col[m]]=1;
    }
    col[m]++;
    }
    else
    { a[col[m]]=b[m+col[m]]=c[n+m-col[m]]=0;
    col[++m]=1;
    }
    else
    { while (col[m]==n)
    { m–;
    a[col[m]]=b[m+col[m]]=c[n+m-col[m]]=1;
    }
    col[m]++;
    }
    good=a[col[m]]&&b[m+col[m]]&&c[n+m-col[m]];
    } while (m!=0);
    }

    试探法找解算法也常常被编写成递归函数,下面两程序中的函数 queen_all()和函数
    queen_one()能分别用来解皇后问题的全部解和一个解。
    【程序】

    include

    include

    10

    define MAXN 20

    int n;
    int col[MAXN+1],a[MAXN+1],b[2MAXN+1],c[2MAXN+1];
    void main()
    { int j;
    printf(“Enter n: “); scanf(“%d”,&n);
    for (j=0;j<=n;j++) a[j]=1;
    for (j=0;j<=2*n;j++) cb[j]=c[j]=1;
    queen_all(1,n);
    }
    void queen_all(int k,int n)
    { int i,j;
    char awn;
    for (i=1;i<=n;i++)
    if (a[i]&&b[k+i]&&c[n+k-i])
    { col[k]=i;
    a[i]=b[k+i]=c[n+k-i]=0;
    if (kn)
    { printf(“列\t 行”);
    for (j=1;j<=n;j++)
    printf(“%3d\t%d\n”,j,col[j]);
    printf(“Enter a character (Q/q for exit)!\n”);
    scanf(“%c”,&awn);
    if (awn
    ’Q’||awn==’q’) exit(0);
    }
    queen_all(k+1,n);
    a[i]=b[k+i]=c[n+k-i];
    }
    }

    采用递归方法找一个解与找全部解稍有不同,在找一个解的算法中,递归算法要对当
    前候选解最终是否能成为解要有回答。当它成为最终解时,递归函数就不再递归试探,立即
    返回;若不能成为解,就得继续试探。设函数 queen_one()返回 1 表示找到解,返回 0 表示
    当前候选解不能成为解。细节见以下函数。
    【程序】

    define MAXN 20

    int n;
    int col[MAXN+1],a[MAXN+1],b[2MAXN+1],c[2MAXN+1];
    int queen_one(int k,int n)
    { int i,found;
    i=found=0;
    While (!found&&i { i++;
    11
    if (a[i]&&b[k+i]&&c[n+k-i])
    { col[k]=i;
    a[i]=b[k+i]=c[n+k-i]=0;
    if (k==n) return 1;
    else
    found=queen_one(k+1,n);
    a[i]=b[k+i]=c[n+k-i]=1;
    }
    }
    return found;
    }
    分支定界法:
    分支限界法:
    这是一种用于求解组合优化问题的排除非解的搜索算法。类似于回溯法,分枝定界法在搜索
    解空间时,也经常使用树形结构来组织解空间。然而与回溯法不同的是,回溯算法使用深度
    优先方法搜索树结构,而分枝定界一般用宽度优先或最小耗费方法来搜索这些树。因此,可
    以很容易比较回溯法与分枝定界法的异同。相对而言,分枝定界算法的解空间比回溯法大得
    多,因此当内存容量有限时,回溯法成功的可能性更大。
    算法思想:分枝定界(branch and bound)是另一种系统地搜索解空间的方法,它与回溯法
    的主要区别在于对 E-节点的扩充方式。每个活节点有且仅有一次机会变成 E-节点。当一个
    节点变为 E-节点时,则生成从该节点移动一步即可到达的所有新节点。在生成的节点中,
    抛弃那些不可能导出(最优)可行解的节点,其余节点加入活节点表,然后从表中选择一个
    节点作为下一个 E-节点。从活节点表中取出所选择的节点并进行扩充,直到找到解或活动
    表为空,扩充过程才结束。
    有两种常用的方法可用来选择下一个 E-节点(虽然也可能存在其他的方法):

    1. 先进先出(F I F O) 即从活节点表中取出节点的顺序与加入节点的顺序相同,因此活
      节点表的性质与队列相同。

    2. 最小耗费或最大收益法在这种模式中,每个节点都有一个对应的耗费或收益。如果查找
      一个具有最小耗费的解,则活节点表可用最小堆来建立,下一个 E-节点就是具有最小耗费
      的活节点;如果希望搜索一个具有最大收益的解,则可用最大堆来构造活节点表,下一个
      E-节点是具有最大收益的活节点
      装载问题
      用一个队列 Q 来存放活结点表,Q 中 weight
      表示每个活结点所相应的当前载重量。当
      weight=-1 时,表示队列已达到解空间树
      同一层结点的尾部。
      算法首先检测当前扩展结点的左儿子结
      点是否为可行结点。如果是则将其加入到活
      结点队列中。然后将其右儿子结点加入到活
      结点队列中(右儿子结点一定是可行结点)。2
      个儿子结点都产生后,当前扩展结点被舍
      弃。
      活结点队列中的队首元素被取出作为
      当前扩展结点,由于队列中每一层结点之后
      都有一个尾部标记-1,故在取队首元素时,
      活结点队列一定不空。当取出的元素是-1
      时,再判断当前队列是否为空。如果队列非
      空,则将尾部标记-1 加入活结点队列,算法
      开始处理下一层的活结点。
      /该版本只算出最优解/
      #include<stdio.h>
      #include<malloc.h>
      struct Queue{
      int weight ;
      12
      struct Queue* next ;
      };
      int bestw = 0 ; // 目前的最优值
      Queue* Q; // 活结点队列
      Queue* lq = NULL ;
      Queue* fq = NULL ;
      int Add(int w)
      {
      Queue* q ;
      q = (Queue*)malloc(sizeof(Queue)) ;
      if(q NULL)
      {
      printf(“没有足够的空间分配\n”) ;
      return 1 ;
      }q->next = NULL ;
      q->weight = w ;
      if(Q->next == NULL)
      { Q->next = q ;
      fq = lq = Q->next ; //一定要使元素放到链
      中}
      else
      {
      lq->next = q ;
      lq = q ;
      // lq = q->next ;
      }
      return 0 ;
      }
      int IsEmpty()
      {
      if(Q->next
      NULL)
      return 1 ;
      return 0 ;
      }
      int Delete(int&w)
      {
      Queue* tmp = NULL ;
      // fq = Q->next ;
      tmp = fq ;
      w = fq->weight ;
      Q->next = fq->next ; /一定不能丢了链表头
      /
      fq = fq->next ;
      free(tmp) ;
      return 0 ;
      }
      void EnQueue(int wt,
      int& bestw, int i, int n) //该函数负责加入
      活结点
      { // 如果不是叶结点,则将结点权值 wt 加
      入队列 Q
      if (i == n)
      { // 叶子
      if (wt>bestw)
      bestw = wt;
      }
      else
      Add(wt); // 不是叶子
      }
      int MaxLoading(int w[], int c, int n)
      { // 返回最优装载值
      // 为层次 1 初始化
      int err ; //返回值
      int i = 1; // 当前扩展结点的层
      int Ew = 0; // 当前扩展结点的权值
      bestw = 0; // 目前的最优值
      Q = (Queue
      )malloc(sizeof(Queue)) ;
      Q->next = NULL ;
      Q->weight = -1 ;
      err = Add(-1) ; //标记本层的尾部
      if(err)
      {
      return 0 ;
      }
      while (true)
      {
      // 检查左孩子结点
      if (Ew + w[i] <= c) // x[i] = 1
      EnQueue(Ew + w[i], bestw , i, n);
      // 右孩子总是可行的
      EnQueue(Ew, bestw, i, n); // x[i] = 0
      Delete(Ew); // 取下一个扩展结点
      if (Ew == -1)
      { // 到达层的尾部
      13
      if (IsEmpty())
      return bestw;
      if(i<n)
      Add(-1); // 同层结点的尾部
      Delete(Ew); // 取下一扩展结点
      i++; // 进入下一层
      }
      }}
      int main()
      {
      int n =0 ;
      int c = 0 ;
      int i = 0 ;
      int
      w ;
      FILE in , out ;
      in = fopen(“input.txt” , “r”) ;
      out = fopen(“output.txt” , “w”) ;
      if(inNULL||outNULL){
      printf(“没有输入输出文件\n”) ;
      return 1 ;
      }
      fscanf(in , “%d” , &n) ;
      fscanf(in , “%d” , &c) ;
      w = (int
      )malloc(sizeof(int)
      (n+1)) ;
      for(i =1 ; i<=n ; i++)
      fscanf(in , “%d” , &w[i]) ;
      MaxLoading(w , c , n) ;
      fprintf(out , “%d\n” , bestw) ;
      return 0 ;
      }
      算法设计与分析期末复习题(四)答案在下面
      一.填空题(每空2分,共30分)
      1.算法的时间复杂性指算法中 的执行次数。
      2.在忽略常数因子的情况下,O、和三个符号中, 提供了算法运行时间的一个上界。
      3.设Dn表示大小为n的输入集合,t(I)表示输入为I时算法的运算时间, p(I)表示输入I出现的概率,则算法的平均情况下时间复杂性A(n)= 。
      4.分治算法的时间复杂性常常满足如下形式的递归方程:

      其中,g(n)表示 。

    1. 分治算法的基本步骤包括 。
      6.回溯算法的基本思想是 。
      7.动态规划和分治法在分解子问题方面的不同点是 。
      8.贪心算法中每次做出的贪心选择都是 最优选择。
      9.PQ式的分支限界法中,对于活结点表中的结点,其下界函数值越小,优先级越 。
      10.选择排序、插入排序和归并排序算法中, 算法是分治算法。
      11.随机算法的一个基本特征是对于同一组输入, 不同的运行可能得到 的结果。
      12.对于下面的确定性快速排序算法,只要在步骤3前加入随机化步骤 ,就可得到一个随机化快速排序算法,该随机化步骤的功能是 。
      算法 QUICKSORT
      输入:n个元素的数组A[1…n]。
      输出:按非降序排列的数组A中的元素。
    2. quicksort(1, n)
      end QUICKSORT
      过程 quicksort(A, low, high)
      // 对A[low…high]中的元素按非降序排序。
    3. if low<high then
    4. w=SPLIT(A, low, high)
      //算法SPLIT以A[low]为主元将A[low…high]划分成两部 //分,返回主元的新位置。
    5. quicksort (A, low, w-1)
    6. quicksort (A, w+1, high)
      6. end if
      end quicksort
      13.下面算法的基本运算是 运算,该算法的时间复杂性阶为( )。
      算法 SPLIT
      输入:正整数n,数组A[1…n]。
      输出:…。
      i=1
      x=A[1]
      for j=2 to n
      if A[j]<=x then
      i=i+1
      if ij then A[i]A[j]
      end if
      end for
      A[i]A[1]
      w =i
      return w, A
      end SPLIT
      二.计算题和简答题(每小题7分,共21分)
      1.用O、、表示函数f与g之间阶的关系,并分别指出下列函数中阶最低和最高的函数:
      (1) f (n)=100 g(n)=
      (2) f(n)=6n+n g(n)=3n
      (3) f(n)= n/logn-1 g(n)=
      (4) f(n)= g(n)=
      (5) f(n)= g(n)=
      2.下面是一个递归算法,其中,过程pro1和pro2的运算时间分别是1和。给出该算法的时间复杂性T(n)满足的递归方程,并求解该递归方程,估计T(n)的阶(用表示)。
      算法 EX1
      输入:正整数n,n=2k。
      输出:…
      ex1(n)
      end EX1
      过程 ex1(n)
      if n=1 then
      pro1(n)
      else
      pro2(n)
      ex1(n/2)
      end if
      return
      end ex1
      3.用Floyd算法求下图每一对顶点之间的最短路径长度,计算矩阵D0,D1,D2和D3,其中Dk[i, j]表示从顶点i到顶点j的不经过编号大于k的顶点的最短路径长度。
      三.算法填空题(共34分)
      1.(10分)设n个不同的整数按升序存于数组A[1…n]中,求使得A[i]=i的下标i 。下面是求解该问题的分治算法。
      算法 SEARCH
      输入:正整数n,存储n个按升序排列的不同整数的数组A[1…n]。
      输出:A[1…n]中使得A[i]=i的一个下标i,若不存在,则输出 no solution。
      i=find ( (1) )
      if i>0 then output i
      else output “no solution”
      end SEARCH
      过程 find (low, high)
      // 求A[low…high] 中使得A[i]=i的一个下标并返回,若不存在,//则返回0。
      if (2) then return 0
      else
      mid=
      if (3) then return mid
      else
      if A[mid]<mid then
      return find( (4) )
      else
      return (5)
      end if
      end if
      end if
      end find
      2.(10分) 下面是求解矩阵链乘问题的动态规划算法。
      矩阵链乘问题:给出n个矩阵M1, M2, …, Mn , Mi 为riri+1阶矩阵,i=1, 2, …, n,求计算M1M2…Mn所需的最少数量乘法次数。
      记 Mi, j=MiMi+1…Mj , i<=j。设C[i, j], 1<=i<=j<=n, 表示计算Mi, j的所需的最少数量乘法次数,则

    算法 MATCHAIN
    输入:矩阵链长度n, n个矩阵的阶r[1…n+1], 其中r[1…n]为n个矩阵的行数,r[n+1]为第n个矩阵的列数。
    输出:n个矩阵链乘所需的数量乘法的最少次数。
    for i=1 to n C[i, i]= (1)
     for d=1 to n-1
    for i=1 to n-d
       j= (2)
    C[i, j]= ∞
    for k=i+1 to j
    x= (3)
    if x<C[i, j] then
    (4) =x
    end if
    end for
    end for
    end for
    return (5)
    end MATCHAIN
    3.(14分) 下面是用回溯法求解马的周游问题的算法。
    马的周游问题:给出一个nxn棋盘,已知一个中国象棋马在棋盘上的某个起点位置(x0, y0),求一条访问每个棋盘格点恰好一次,最后回到起点的周游路线。(设马走日字。)
    算法 HORSETRAVEL
    输入:正整数n,马的起点位置(x0, y0),1<=x0, y0<=n 。
    输出:一条从起点始访问nxn棋盘每个格点恰好一次,最后回到起点的周游路线;若问题无解,则输出no solution。
    tag[1…n, 1…n]=0
    dx[1…8]={2, 1, -1, -2, -2, -1, 1, 2}
    dy[1…8]={1, 2, 2, 1, -1, -2, -2, -1}
    flag=false
    x=x0; y=y0 ; tag[x, y]=1
    m=n*n
    i=1; k[i]=0
    while (1) and not flag
    while k[i]<8 and not flag
    k[i]= (2)
    x1= x+dx[k[i]]; y1= y+dy[k[i]]
    if ((x1,y1)无越界and tag[x1, y1]=0) or ((x1,y1)=(x0,y0) and i=m) then
    x=x1; y=y1
    tag[x, y]= (3)
    if i=m then flag=true
    else
    i= (4)
    (5)
    end if
    end if
    end while
    i=i-1
    (6)
      (7)
    end while
    if flag then outputroute(k) //输出路径
    else output “no solution” 
    end HORSETRAVEL
    四.算法设计题(15分)
    10. 一个旅行者要驾车从A地到B地,A、B两地间距离为s。A、B两地之间有n个加油站,已知第i个加油站离起点A的距离为公里,0=,车加满油后可行驶m公里,出发之前汽车油箱为空。应如何加油使得从A地到B地沿途加油次数最少?给出用贪心法求解该最优化问题的贪心选择策略,写出求该最优化问题的最优值和最优解的贪心算法,并分析算法的时间复杂性。
    《算法设计与分析》期考试卷(A)标准答案

    一.填空题:

    1. 元运算
    2. O
    3. 将规模为n的问题分解为子问题以及组合相应的子问题的解所需的时间
    4. 分解,递归,组合
    5. 在问题的状态空间树上作带剪枝的DFS搜索(或:DFS+剪枝)
    6. 前者分解出的子问题有重叠的,而后者分解出的子问题是相互独立(不重叠)的
    7. 局部
    8. 归并排序算法
    9. 不同
    10. v=random (low, high); 交换A[low]和A[v]的值
      随机选主元
    11. 比较
      n

    二.计算题和简答题:

    1. 阶的关系:
      (1) f(n)= O(g(n))
      (2) f(n)=(g(n))
      (3) f(n)=(g(n))
      (4) f(n)= O(g(n))
      (5) f(n)=(g(n))
      阶最低的函数是:100
      阶最高的函数是:
    2. 该递归算法的时间复杂性T(n)满足下列递归方程:

    将n=, a=1, c=2, g(n)=, d=1代入该类递归方程解的一般形式得:
    T(n)=1+=1+k-
    =1+ k-=++1
    所以,T(n)= ++1=。
    3.

    三.算法填空题:
    1.(1) 1, n (2) low>high (3) A[mid]=mid
    (4) mid+1, high (5) find(low, mid-1)
    2. (1) 0 (2) i+d (3) C[i, k-1]+C[k, j]+r[i]*r[k]*r[j+1]
    (4) C[i, j] (5) C[1, n]
    3. (1) i>=1 (2)k[i]+1 (3) 1
    (4) i+1 (5) k[i]=0 (6) tag[x, y]=0
    (7) x=x-dx[k[i]]; y=y-dy[k[i]]

    四.算法设计题:

    1. 贪心选择策略:从起点的加油站起每次加满油后不加油行驶尽可能远,直至油箱中的油耗尽前所能到达的最远的油站为止,在该油站再加满油。
      算法 MINSTOPS
      输入:A、B两地间的距离s,A、B两地间的加油站数n,车加满油后可行驶的公里数m,存储各加油站离起点A的距离的数组d[1…n]。
      输出:从A地到B地的最少加油次数k以及最优解x[1…k](x[i]表示第i次加油的加油站序号),若问题无解,则输出no solution。
      d[n+1]=s; //设置虚拟加油站第n+1站。
      for i=1 to n
      if d[i+1]-d[i]>m then
      output “no solution”; return //无解,返回
      end if
      end for
      k=1; x[k]=1 //在第1站加满油。
      s1=m //s1为用汽车的当前油量可行驶至的地点与A点的距离
      i=2
      while s1<s
      if d[i+1]>s1 then //以汽车的当前油量无法到达第i+1站。
      k=k+1; x[k]=i //在第i站加满油。
      s1=d[i]+m //刷新s1的值
      end if
      i=i+1
      end while
      output k, x[1…k]
      MINSTOPS

    最坏情况下的时间复杂性:Θ(n)
    算法设计与分析期末复习题(五)
    一、选择题
    1.一个.java文件中可以有( )个public类。
    A.一个 B.两个 C.多个 D.零个
    2.一个算法应该是( )
    A.程序 B.问题求解步骤的描述
    C.要满足五个基本特性 D.A和C
    3.用计算机无法解决“打印所有素数”的问题,其原因是解决该问题的算法违背了算法特征中的( )
    A.唯一性 B.有穷性 C.有0个或多个输入 D.有输出
    4.某校有6位学生参加学生会主席竞选,得票数依次为130,20,98,15,67,3。若采用冒泡排序算法对其进行排序,则完成第二遍时的结果是( )

    A.3,15,130,20,98,67 B.3,15,20,130,98,67
    C.3,15,20,67,130,98 D.3,15,20,67,98,130
    5.下列关于算法的描述,正确的是( )
    A.一个算法的执行步骤可以是无限的 B.一个完整的算法必须有输出
    C.算法只能用流程图表示 D.一个完整的算法至少有一个输入
    6.Java Application源程序的主类是指包含有( )方法的类。
    A、main方法 B、toString方法 C、init方法 D、actionPerfromed方法
    7.找出满足各位数字之和等于5的所有三位数可采用的算法思路是( )
    A.分治法 B.减治法 C.蛮力法 D.变治法
    8.在编写Java Application程序时,若需要使用到标准输入输出语句,必须在程序的开头写上( )语句。
    A、import java.awt.* ; B、import java.applet.Applet ;
    C、import java.io.* ; D、import java.awt.Graphics ;
    9.计算某球队平均年龄的部分算法流程图如图所示,其中:c用来记录已输入球员的人数,sum用来计算有效数据之和,d用来存储从键盘输入的球员年龄值,输入0时表示输入结束。

    图中空白处理框①和②处应填入的是( )
    A.① sum ← sum + d B.① sum ← sum + c
    ② c ← c + 1 ② c ← c + 1
    C.① sum ← sum + d D.① sum ← sum + c
    ② d ← d + 1 ② d ← d + 1
    10.报名参加冬季越野赛跑的某班5位学生的学号是:5,8,11,33,45。利用折半查找,查找学号为33号学生的过程中,依次被访问到的学号是( )
    A.5,11,33 B.8,33 C.11,45,33 D.11,33
    11.表达式(short)8/9.2*5的值的类型为
    A.short B. int C.double D.float
    12. 设x为int型变量,则执行一下语句段后,x的值为
    x=10;
    x+=x-=x-x;
    A.10 B.20 C.40 D.30
    13.下列代码的执行结果是
    public class StringTest{
    public static void main(String args[]){
    int a=4,b=6,c=8;
    String s=”abc”;
    System.out.println(a+b+s+c);
    System.out.printin(); }
    }
    A.ababcc B.464688 C.46abc8 D.10abc8
    14. 下列程序段执行后t3的结果是
    int t1 = 2, t2 = 3, t3;
    t3=t1<t2? t1:t2+t1
    A.2 B.4 C.5 D.6
    15.要计算当0〈x〈10时,y=x,应当使用的语句是
    A.if(0<x<10)y=x; B.if(0<x|x<10)y=x; C.if(0<x&x<10)y=x; D.if(0<x^x<10)y=x;
    16.对一组数据(2,12,16,88,5,10)进行排序,若前三趟排序结果如下,
    第一趟:2,12,16,88,5,10
    第二趟:2,5,16,88,12,10
    第三趟:2,5,10,88,12,16
    则采用的排序方法是( )
    A.冒泡排序 B.合并排序 C.快速排序 D.选择排序
    17.类与对象的关系是( )
    A. 建筑图纸和建筑物的关系 B. 汽车与发动机的关系
    C. 人与黑人的关系 D. 没有关系
    18.JAVA语言二维数组定义中,第二维的长度 ( )
    A.可以不相等 B.必须相等
    C.高维数组长度与低维数组长度相同 D.固定长度
    19.算法必须具备( )这三个特性。
    A.可执行性、可移植性、可扩充性 B.可执行性、确定性、有穷性
    C.确定性、有穷性、稳定性 D.易读性、稳定性、安全性
    20.如下图所示,该流程图所表示的算法违背了算法的有穷性特征,下列修改方法中,可以改正该错误的是( )

    A.将①处改为 i ← 0 B.将②处改为 s ≥ 0 ?
    C.将③处改为 i ← i-2 D.将④处改为 s ← s-i

    二、填空题
    1.一个显而易见的事实是:大部分算法的执行时间随着 输入量的增加 而增大。
    2.算法是 求解某一问题所使用的一系列清晰的指令 。
    3.算法分析时间效率模型的基本数学公式是: T(n) ≈ CopC(n) 。
    4.算法设计技术是 用算法解题的一般性方法 ,用于解决不同计算领域的多种问题。
    5.三个渐进符号: O 、 Ω 和 Ө 。
    6.效率分析框架主要关心一个算法的 基本操作次数的增长次数 ,并把它作为算法效率的主要指标。
    7.Java源程序的文件名和程序中定义的 主类名 应保持一致,包括字母大小写的匹配。
    8.算法中常见的问题类型包括: 排序 、 查找 、字符串处理和组合问题等。
    9.类中的 构造 方法是一个特殊的方法,其名称与类名相同。
    10.面向对象程序设计语言中的3个重要特性分别是 封装 、 继承 和 多态 。
    11.Java源程序文件的扩展名为 java ,编译生成的字节码文件的扩展名为 class 。
    12.大多数算法的效率可以分为常数、 对数 、线性、平方、 立方 和指数等。

    三、简答题
    1.什么是算法?算法的五个重要特征是什么?
    答:算法是求解某一问题所使用的一系列清晰的指令。
    答:
    (1)输入:有零个或多个由外部提供的量作为算法的输入.
    (2)输出:算法产生至少一个量作为输出.
    (3)确定性:组成算法的每条指令是清晰的,无歧义的.
    (4)有限性:在执行了有穷步骤后运算终止.
    (5)可行性:运算都是基本运算,原理上能在有限时间内完成.

    2.请简述蛮力算法的优点?
    答:
    蛮力算法是一种简单直接地解决问题的方法。蛮力法具有如下优点:(1)应用范围广;(2)不受实例规模的限制;(3)当要解决的问题实例不多,设计更高效算法的代价太大时可选用;(4)对解决一些小规模的问题实例仍然有效;(5)可作为衡量其他算法的参照物。

    3.算法设计与分析过程的典型步骤都包括哪些?
    答:
    (1)了解问题的内容
    (2)了解计算设备的性能
    (3)在精确解法和近似解法之间选择
    (4)确定适当的数据结构
    (5)算法设计技术
    (6)详细表述算法的方法
    (7)证明算法的正确性
    (8)分析算法
    (9)为算法写代码

    4.请简述分治法的基本思路?
    答:
    将规模为N的问题分解为k个规模较小的子问题,使这些子问题相互独立可分别求解,再将k个子问题的解合并成原问题的解。如子问题的规模仍很大,则反复分解直到问题小到可直接求解为止。
    在分治法中,子问题的解法通常与原问题相同,自然导致递归过程。

    5.请简述减治法的基本思路?
    答:
    减治技术利用了一个问题给定实例的解和同样问题较小实例的解之间的某种关系。一旦建立了这种关系,既可以从顶至底(递归地),也可以从底至顶(非递归地)来运用该关系。
    减治法有三种主要的变种:
    减常数(如1)::每此迭代规模减小n→n-1
    减因子(如1/2):每此迭代规模减半n→ n/2
    减可变规模:每此迭代减小的规模不同

    6.请简述递归算法设计的基本思路?
    答:
    递归的执行过程由分解过程和求值过程两部分构成。
    实际上, 递归思路是把一个不能或不好直接求解的“大问题”转化成一个或几个“小问题”来解决,再把这些“小问题”进一步分解成更小的“小问题”来解决,如此分解,直至每个“小问题”都可以直接解决(此时分解到递归出口)。
    但递归分解不是随意的分解,递归分解要保证“大问题”与“小问题”相似,即求解过程与环境都相似。并且有一个分解的终点。从而使问题可解。

    7.请简述变治法的基本思路?
    答:
    变治法的技术基于变换思想。变治法分为两个阶段的工作:首先在“变”的阶段,出于这样或那样的原因,将问题的实例变得更容易求解;然后是“治”的阶段,对问题的实例进行求解。
    根据对问题实例的变换方式不同,变治法有三种主要的类型:
    (1)实例化简——变换为同样问题的一个更简单或者更方便的实例;
    (2)改变表现——变换为同样实力的不同表现;
    (3)问题化简——变换为另一个问题的实例,这种问题的算法是已知的。
    8.请简述时空权衡法的基本思路?
    答:
    时空权衡法的基本思路是对问题的部分或全部输入做预处理,然后对得到的额外信息使用额外的存储空间来存储。通过实现更快或更方便的数据存取,以加速后面问题的求解来提高算法的效率。

    四、算法实现题
    1.对于任意非负整数n,计算阶乘函数F(n) = n!的值。因为当n ≥ 1时,n!= 1×2×3×……×(n-1)×n = (n-1)!×n。并且根据定义,0!= 1,所以可以使用下面的递归算法计算n!:F(n) = F(n-1) × n。
    请编写Java应用程序,由键盘输入n的值,在屏幕上输出计算的n!的结果。
    import java.io.*;
    public class FN
    {
    static long f(int n)
    {
    long r = 1;
    if(n != 0)
    r = n * f(n-1);
    return r;
    }
    public static void main(String args[]) throws IOException
    {
    //输入N的值
    byte[] buf = new byte[10];
    System.out.println(“请输入一个整数:”);
    System.in.read(buf);
    String str=new String(buf);
    int n=Integer.parseInt(str.trim());
    //计算N!的值
    long result = f(n);
    //输出结果
    System.out.println(n + “!=” + result);
    }
    }

    2.斐波那契数列:0,1,1,2,3,5,8,13,21,34,……
    这个数列可以用一个简单的递推式和两个初始条件来定义:
    当n > 1时,F(n) = F(n-1) + F(n-2)
    F(0) = 0,F(1) = 1

    请编写Java应用程序,由键盘输入n的值代表要生成斐波那契数列的项数,在屏幕上输出n项斐波那契数列。
    import java.io.*;
    public class Fb{
    /斐波那契数列算法/
    int f(int n){
    int r;
    if(n <= 1)
    r = n;
    else
    r = f(n-1) + f(n-2);
    return r;
    }
    public static void main(String args[]) throws IOException{
    System.out.println(“请输入所求斐波那契数列的项数:”);
    byte buf[] = new byte[20];
    System.in.read(buf);
    String t1 = new String(buf);
    int n = Integer.parseInt(t1.trim());
    Fb f1 = new Fb();
    int b;
    System.out.println(“输出包含” + n + “项的斐波那契数列:”);
    for(int i = 0; i <= n; i++)
    {
    b = f1.f(i);
    System.out.print(b + " ");
    }
    System.out.println();
    }
    }

    3.编写基于Java语言的选择排序算法。
    /***

    • 功能:该算法用选择排序对给定的数组排序
    • 输入:一个乱序的整数数组a[ ]
    • 输出:升序排列的整数数组a[ ]
      ***/
      public void selectionSort (int a[ ])
      {
      int temp,min;
      for(int i=0;i<a.length-1;i++)
      {
      min = i;
      for(int j=i+1;j<a.length;j++)
      if(a[min] > a[j])
      min = j;
      temp = a[i];
      a[i] = a[min];
      a[min] = temp;
      }
      }

    4.编写基于Java语言的冒泡排序算法。
    /***

    • 功能:该算法用冒泡排序对给定的数组排序
    • 输入:一个乱序的整数数组a[ ]
    • 输出:升序排列的整数数组a[ ]
      ***/
      public void bubbleSort(int a[ ])
      {
      int temp;
      for(int i=0;i<a.length-1;i++)
      for(int j=0;j<a.length-1-i;j++)
      if(a[j]>a[j+1])
      {
      temp = a[j+1];
      a[j+1] = a[j];
      a[j] = temp;
      }
      }

    5.编写基于Java语言的顺序查找算法。
    /***

    • 功能:该算法实现顺序查找功能

    • 输入:一个整数数组a[ ]和一个要查找的键值k

    • 输出:如果在数组中找到k,则返回对应数组元素的下标;如果在数组中找不到k,则返回-1
      ***/
      public int seqSearch(int a[ ],int k)
      {
      int i = 0;
      while((i < a.length ) && ( a[i] != k ))
      i = i + 1;
      if( i < a.length)

        	return i;
        else
      
        	return -1;
      

    }

    6.编写基于Java语言的折半查找算法。
    /***

    • 功能:该算法实现折半查找功能
    • 输入:一个已经按照升序排列好的整数数组a[ ]和一个要查找的键值k
    • 输出:如果在数组中找到k,则返回对应数组元素的下标;如果在数组中找不到k,则返回-1
      ***/
      public int binarySearch(int a[ ], int k)
      {
      int low = 0;
      int upper = a.length - 1;
      while(low <= upper)
      {
      int mid = (low+upper) / 2;
      if(k == a[mid])
      return mid;
      else
      if(des < a[mid])
      upper = mid - 1;
      else
      low = mid + 1;
      }
      return -1;
      }

    7.编写基于Java语言的字符串匹配算法。
    /***

    • 功能:该算法实现字符串匹配功能

    • 输入:一个n个字符的字符串str代表一段文本
      一个m个字符的字符串key代表一个模式

    • 输出:如果查找成功的话,返回文本的第一个匹配字符串中第一个字符的位置,
      否则返回-1
      ***/
      public int stringMatch(String str,String key)
      {
      int j;
      int n = str.length();
      int m = key.length();

        for(int i = 0; i <= (n - m); i++)
        {
        	j = 0;
        	while((j < m) && (key.charAt(j) == str.charAt(i+j)))
        	{
        		j = j + 1;
        		System.out.println(i + "," + j);
        		if(j == m)
        			return i;
        	}
        }
        return -1;
      

    }

    8.编写基于Java语言的直接插入排序算法。
    /***

    • 功能:该算法用直接插入排序对给定的数组排序
    • 输入:一个乱序的整数数组a[ ]
    • 输出:升序排列的整数数组a[ ]
      ***/
      public void insertSort (int a[ ])
      {
      int temp,i,j;
      for(i=1;i<a.length;i++)
      {
      temp=a[i];
      j=i-1;
      while(j>=0 && a[j]>=temp)
      {
      a[j+1]=a[j];
      j–;
      }
      a[j+1]=temp;
      }
      }
      算法设计与分析期末复习题(六)
      1、用计算机求解问题的步骤:
      1、问题分析2、数学模型建立3、算法设计与选择4、算法指标5、算法分析6、算法实现7、程序调试8、结果整理文档编制
      2、算法定义:算法是指在解决问题时,按照某种机械步骤一定可以得到问题结果的处理过程
      3、算法的三要素
      1、操作2、控制结构3、数据结构
      算法具有以下5个属性:
       有穷性:一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成。
       确定性:算法中每一条指令必须有确切的含义。不存在二义性。只有一个入口和一个出口
       可行性:一个算法是可行的就是算法描述的操作是可以通过已经实现的基本运算执行有限次来实现的。
       输入:一个算法有零个或多个输入,这些输入取自于某个特定对象的集合。
       输出:一个算法有一个或多个输出,这些输出同输入有着某些特定关系的量。
      算法设计的质量指标:
        正确性:算法应满足具体问题的需求;
        可读性:算法应该好读,以有利于读者对程序的理解;
        健壮性:算法应具有容错处理,当输入为非法数据时,算法应对其作出反应,而不是产生莫名其妙的输出结果。
        效率与存储量需求:效率指的是算法执行的时间;存储量需求指算法执行过程中所需要的最大存储空间。一般这两者与问题的规模有关。

    经常采用的算法主要有迭代法、分而治之法、贪婪法、动态规划法、回溯法、分支限界法

    迭代法
    基本思想:迭代法也称“辗转法”,是一种不断用变量的旧值递推出新值的解决问题的方法。
    解题步骤:1、确定迭代模型。根据问题描述,分析得出前一个(或几个)值与其下一个值的迭代关系数学模型。
    2、建立迭代关系式。迭代关系式就是一个直接或间接地不断由旧值递推出新值的表达式,存储新值的变量称为迭代变量
    3、对迭代过程进行控制。确定在什么时候结束迭代过程,这是编写迭代程序必须考虑的问题。不能让迭代过程无休止地重复执行下去。迭代过程的控制通常可分为两种情况:一种是所需的迭代次数是个确定的值,可以计算出来;另一种是所需的迭代次数无法确定。对于前一种情况,可以构建一个固定次数的循环来实现对迭代过程的控制;对于后一种情况,需要进一步分析出用来结束迭代过程的条件。
    编写计算斐波那契(Fibonacci)数列的第n项函数fib(n)。
     
      写成递归函数有:
      int fib(int n)
      { if (n0) return 0;
      if (n
    1) return 1;
      if (n>1) return fib(n-1)+fib(n-2);
      }

    一个饲养场引进一只刚出生的新品种兔子,这种兔子从出生的下一个月开始,每月新生一只兔子,新生的兔子也如此繁殖。如果所有的兔子都不死去,问到第 12 个月时,该饲养场共有兔子多少只?
    Main()
    {int I,a=1,b=1;
    Print(a,b);
    For(i=1;i<=10;i++)
    {
    C=a+b;
    Print©;
    A=b;
    B=c;
    }
    }

    分而治之法
    1、基本思想
    将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
    分治法所能解决的问题一般具有以下几个特征:
    (1)该问题的规模缩小到一定的程度就可以容易地解决;
    (2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
    (3)利用该问题分解出的子问题的解可以合并为该问题的解;
    (4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
    3、分治法的基本步骤
    (1)分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
    (2)解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
    (3)合并:将各个子问题的解合并为原问题的解。

    贪婪法
    基本思想:以逐步的局部最优,达到最终的全局最优。无后效性

    【问题】 背包问题
    问题描述:有不同价值、不同重量的物品n件,求从这n件物品中选取一部分物品的选择方案,使选中物品的总重量不超过指定的限制重量,但选中物品的价值之和最大。

    #include<stdio.h>
    void main()
    {
    int m,n,i,j,w[50],p[50],pl[50],b[50],s=0,max;
    printf(“输入背包容量m,物品种类n :”);
    scanf("%d %d",&m,&n);
    for(i=1;i<=n;i=i+1)
    {
    printf(“输入物品的重量W和价值P :”);
    scanf("%d %d",&w[i],&p[i]);
    pl[i]=p[i];
    s=s+w[i];
    }
    if(s<=m)
    {
    printf(“whole choose\n”);
    //return;
    }
    for(i=1;i<=n;i=i+1)
    {
    max=1;
    for(j=2;j<=n;j=j+1)
    if(pl[j]/w[j]>pl[max]/w[max])
    max=j;
    pl[max]=0;
    b[i]=max;
    }
    for(i=1,s=0;s<m && i<=n;i=i+1)
    s=s+w[b[i]];
    if(s!=m)
    w[b[i-1]]=m-w[b[i-1]];
    for(j=1;j<=i-1;j=j+1)
    printf(“choose weight %d\n”,w[b[j]]);

    }
    动态规划
    基本思想:把求解的问题分成许多阶段或多个子问题,然后按顺序求解各个子问题。前一个子问题的解为后一个子问题的求解提供了有用的信息。在求解任何一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解,依次解决各子问题,最后一个子问题就是问题的解。
    基本步骤
    (1)划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。注意这若干个阶段一定要是有序的或者是可排序的(即无后向性),否则问题就无法用动态规划求解。
    (2)选择状态:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。当然,状态的选择要满足无后效性。
    (3)确定决策并写出状态转移方程:之所以把这两步放在一起,是因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以,如果我们确定了决策,状态转移方程也就写出来了。但事实上,我们常常是反过来做,根据相邻两段的各状态之间的关系来确定决策。
    回溯法
    基本思想:按照深度优先策略,从根结点出发搜索解空间。算法搜索至解空间的任一结点时总是先判断该结点是否问题的约束条件。如果满足进入该子树,继续按深度优先的策略搜索。否则,不去搜索以该结点为根的子树,而是逐层向其祖先结点回溯。其实回溯法就是对隐式图的深度优先搜索算法
    基本步骤:
    1、确定问题的解空间:应用回溯法时,首先应明确定义问题的解的空间。问题的解空间应至少包含问题的一个解。
    2、确定结点的扩展规则
    3、搜索解空间:从开始结点出发,以深度优先的方式搜索整个解空间。
    【问题】 n皇后问题
    分支限界法
    基本思想: 分支限界法是由“分支”和“限界”两部分组成。“分支”策略体现在对问题空间是按广度优先的策略进行搜索“限界”策略是为了加速搜索速度面采用启发信息剪枝策略。
    可能会让画出“子集树斩图”235页例题及图好好看一下。
    整理不易喜欢的点个赞呗!

    展开全文
  • 算法设计与分析期末试题及答案 内含3套试题和完整答案。
  • 为2019年1月考试而准备的复习重点。 根据张署老师2019秋季给的重点,自己又结合之前讲课的ppt总结而成,涵盖了所有考点,精简意赅,建议看完老师ppt后再来看我总结的知识点。
  • 计算机算法设计与分析期末试题
  • 考试题型 选择题算法类型时间复杂度共1530分 简答题设计思想共212分 应用解题步骤搜索空间树等共448分 编程上机实验作业等共110分;2019/12/25;自然语言 优点容易理解 缺点冗长二义性 使用方法粗线条...
  • 算法分析与设计期末试题及参考答案.doc 上传人:max****ui文档编号:16475810上传时间:2019-03-15格式:DOC页数:13大小:126.39KB下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览、不比对...
  • 天津大学算法设计与分析复习资料,包含有老师上课过程中所使用过的课件,课件内容涵盖了动态规划,贪心,分治等所种算法,并配套有一定数量的习题可供参考。
  • 目录贪心算法贪心算法优化问题贪心算法概述贪心算法的基本要素贪心选择性质最优子结构贪心法的步骤贪心法的主要特点贪心法的正确性证明贪心算法问题举例活动安排问题问题描述算法描述代码算法正确性的证明复杂度01...
  • 本次考试是山东大学软件学院2019级软件工程专业大三上算法期末考试 本学期的算法课上课时间为2-7周,9-14周(实际上13周就结束了),第15周考试 考试范围:除了并查集和35章近似算法不考,其他在老师PPT上的内容都是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,265
精华内容 506
关键字:

算法设计与分析期末考试试题