当前位置:文档之家› 《算法分析与设计》_实验指导书

《算法分析与设计》_实验指导书

编著说明本书是为配合《算法分析与设计实验教学大纲》而编写的上机指导,其目的是使学生消化理论知识,加深对讲授内容的理解,尤其是一些算法的实现及其应用,培养学生独立编程和调试程序的能力,使学生对算法的分析与设计有更深刻的认识。

上机实验一般应包括以下几个步骤:(1)、准备好上机所需的程序。

手编程序应书写整齐,并经人工检查无误后才能上机。

(2)、上机输入和调试自己所编的程序。

一人一组,独立上机调试,上机时出现的问题,最好独立解决。

(3)、上机结束后,整理出实验报告。

实验报告应包括:题目、程序清单、运行结果、对运行情况所作的分析。

本书共分8~10个实验,其具体要求和步骤如下:目录实验一、C/C++环境及递归算法...................................... 错误!未定义书签。

实验二、递归与分治策略.. (5)实验三、动态规划算法(一) (9)实验四、动态规划算法(二) (12)实验五、贪心算法(一) (15)实验六、贪心算法(二) (17)实验七、回溯法(一) (20)实验八、回溯算法(二) (22)实验九、分支限界法 (24)实验十:随机化算法(选学) (29)实验二、递归与分治策略一、实验目的与要求1、进一步熟悉C/C++语言的集成开发环境;2、通过本实验加深对递归与分治策略的理解和运用;二、实验内容:1、分析并掌握“棋盘覆盖问题”的递归与分治算法示例;2、分析并掌握“二分搜索问题”的递归与分治算法示例;3、练习使用递归与分治策略求解众数问题或集合划分问题;三、实验题众数问题:给定含有N个元素的多重集合S,每个元素在S中出现的次数称为该元素的重数,多重集合S中重数最大的元素称为多重集合S的众数,众数的重数称为多重集合S的重数,试求一个给定多重结合的重数和众数;例如:S={a,b,b,b,f,f,4,5}的重数是3,众数是b集合划分问题:N个元素的集合{1,2,…,N}可以划分为若干个非空集合的子集,例如,当N=4时,集合{1,2,3,4}可划分为15个不同的非空子集如下:{{1},{2},{3},{4}};{{1,2},{3},{4}};{{1,3},{2},{4}};{{1,4},{2},{3}};{{2,3 },{1},{4}};{{2,4},{1},{3 }};{{3,4 },{1},{2}};{{1,2 },{3,4}};{{1,3 },{2,4}};{{1,4 },{3,2 }};{{2,3,4},{1}};{{1,3,4},{2}};{{1,2,4},{3}};{{1,2,3},{4}};{{1,2,3,4}};给定正整数N,计算出N个元素的集合{1,2,…,N}可以划分多少个非空集合的子集;四、实验步骤1.理解递归和分治策略的基本思想和算法示例;2.上机输入和调试算法示例程序;3.理解实验题的问题要求;4.上机输入和调试自己所编的实验题程序;5.验证并分析实验题的实验结果;6.整理出实验报告;五、递归与分治算法示例程序1、棋盘覆盖问题:在一个2k×2k 个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。

在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖;void chessBoard(int tr, int tc, int dr, int dc, int size){if (size == 1) return;int t = tile++, // L型骨牌号s = size/2; // 分割棋盘// 覆盖左上角子棋盘if (dr < tr + s && dc < tc + s) // 特殊方格在此棋盘中chessBoard(tr, tc, dr, dc, s);else {// 此棋盘中无特殊方格board[tr + s - 1][tc + s - 1] = t; // 用t 号L型骨牌覆盖右下角chessBoard(tr, tc, tr+s-1, tc+s-1, s); // 覆盖其余方格}// 覆盖右上角子棋盘if (dr < tr + s && dc >= tc + s) // 特殊方格在此棋盘中chessBoard(tr, tc+s, dr, dc, s);else {// 此棋盘中无特殊方格board[tr + s - 1][tc + s] = t; // 用t 号L型骨牌覆盖左下角// 覆盖其余方格chessBoard(tr, tc+s, tr+s-1, tc+s, s);}// 覆盖左下角子棋盘if (dr >= tr + s && dc < tc + s) // 特殊方格在此棋盘中chessBoard(tr+s, tc, dr, dc, s);else {board[tr + s][tc + s - 1] = t; // 用t 号L型骨牌覆盖右上角// 覆盖其余方格chessBoard(tr+s, tc, tr+s, tc+s-1, s)}// 覆盖右下角子棋盘if (dr >= tr + s && dc >= tc + s) // 特殊方格在此棋盘中chessBoard(tr+s, tc+s, dr, dc, s);else {board[tr + s][tc + s] = t; // 用t 号L型骨牌覆盖左上角chessBoard(tr+s, tc+s, tr+s, tc+s, s); // 覆盖其余方格}}2、二分搜索问题:⑴、设:a[0:n-1]是一个已排好序的数组。

请改写二分搜索算法,使得当搜索元素x 不在数组中时,返回小于x的最大元素的位置I和大于x的最大元素位置j。

当搜索元素在数组中时,I和j相同,均为x在数组中的位置。

⑵、设:有n个不同的整数排好序后存放于t[0:n-1]中,若存在一个下标I,0≤i<n,使得t[i]=i,设计一个有效的算法找到这个下标。

要求算法在最坏的情况下的计算时间为O(logn)。

⑶、用I,j做参数,且采用传递引用或指针的形式带回值。

bool BinarySearch(int a[],int n,int x,int& i,int& j){int left=0;int right=n-1;while(left<right){int mid=(left+right)/2;if(x==a[mid]){i=j=mid;return true;}if(x>a[mid])left=mid+1;elseright=mid-1;}i=right;j=left;return false;}int SearchTag(int a[],int n,int x) {int left=0;int right=n-1;while(left<right){int mid=(left+right)/2;if(x==a[mid])return mid;if(x>a[mid])right=mid-1;elseleft=mid+1;}return -1;}实验三、动态规划算法(一)一、实验目的与要求1.通过动态规划算法的示例程序理解动态规划算法的基本思想;2.运用动态规划算法解决实际问题加深对动态规划算法的理解和运用;二、实验内容:1.分析并掌握“最长公共子序列”问题的动态规划算法求解方法;2.练习使用动态规划算法求解“游艇租用”问题;三、实验题游艇租用问题:长江旅游俱乐部在长江上设置了N个游艇出租站1,2,3,…,N,游客在这些站中租用游艇,并在下游的任何一个游艇出租站归还,游艇出租站i到游艇出租站j之间的租金为r(i,j),1≤i<j≤N;试求出从游艇出租站1到游艇出租站N所需的最少租金及其游艇租用和归还方案;四、实验步骤1.理解动态规划算法思想和算法示例;2.上机输入和调试算法示例程序;3.理解实验题的问题要求;4.上机输入和调试自己所编的实验题程序;5.验证并分析实验题的实验结果;6.整理出实验报告;五、动态规划算法示例程序最长公共子序列问题:若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。

例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。

给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。

给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。

include "stdlib.h"#include "string.h"void LCSLength(char *x ,char *y,int m,int n, int **c, int **b){int i ,j;for (i = 1; i <= m; i++) c[i][0] = 0;for (i = 1; i <= n; i++) c[0][i] = 0;for (i = 1; i <= m; i++)for (j = 1; j <= n; j++){if (x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}else if (c[i-1][j]>=c[i][j-1]){c[i][j]=c[i-1][j];b[i][j]=2;}else{ c[i][j]=c[i][j-1];b[i][j]=3;}}}void LCS(int i ,int j, char *x ,int **b) {if (i ==0 || j==0) return;if (b[i][j]== 1){LCS(i-1,j-1,x,b);printf("%c",x[i]);}else if (b[i][j]== 2)LCS(i-1,j,x,b);else LCS(i,j-1,x,b);}实验四、动态规划算法(二)一、实验目的与要求1、通过动态规划算法的示例程序进一步理解动态规划算法的基本思想;2、运用动态规划算法解决实际问题进一步加深对动态规划算法的理解和运用;二、实验内容:1、分析并掌握“最大字段和” 问题的动态规划算法求解方法;2、练习使用动态规划算法求解“石子合并”问题;三、实验题石子合并问题:在一个圆形操场的四周摆放着数量相同或不同的N 堆石子,现将N 堆石子有序地合并一堆,规定每次只能将相邻的2堆石子合并成新的一堆石子,并将新的一堆石子数记为该次合并的得分,试设计一个算法,计算出将N 堆石子合并成一堆的最小和最大得分;四、实验步骤1.理解动态规划算法思想和算法示例; 2.上机输入和调试算法示例程序; 3.理解实验题的问题要求;4.上机输入和调试自己所编的实验题程序; 5.验证并分析实验题的实验结果; 6.整理出实验报告;五、动态规划算法示例程序最大字段和问题:若给定n 个整数(可能有负整数)组成的序列n a a a ,,,21 ,求该序列中形如形如∑=jik k a ,( n j i ≤≤≤1)的字段和的最大值。

相关主题