算法设计.docx
- 文档编号:8009008
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:12
- 大小:54.08KB
算法设计.docx
《算法设计.docx》由会员分享,可在线阅读,更多相关《算法设计.docx(12页珍藏版)》请在冰豆网上搜索。
算法设计
算法分析与设计实验报告
学院:
专业:
学号:
姓名:
.
目录
一、实验要求
二、实验内容与思想设计
三、测试结果
四、实验心得
五、附:
源程序
一、实验要求
实验一
棋盘覆盖问题
在一个2kx2k(即:
2^kx2^k)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。
在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
Input
输入文件第一行是一个整数T,表示有多少组测试数据,接下来是T组测试数据,共2T行,每组第一行为整数n,是2的n次幂(1<=n<=64),表示棋盘的大小为n*n,第二行是两个整数,代表特殊方格所在行号和列号。
Output
先输出“CASE:
i,然后按样例输出。
数据间用制表符隔开(‘t’),每行最后一个数据后无制表符。
SampleInput
2
2
00
8
22
SampleOutput
CASE:
1
01
11
CASE:
2
33448899
32248779
52061010711
55661101111
13131411181919
1312141418181719
1512121620171721
1515161620202121
实验二
众数问题
给定含有n个元素的多重集合S,每个元素在S中出现的次数称为该元素的重数。
多重集S中重数最大的元素称为众数。
例如,S={1,2,2,2,3,5}。
多重集S的众数是2,其重数为3。
数据输入
输入包括多组数据,请处理到EOF结束。
每组数据,以一个n(1<=n<=100,000)开始,接下n行,每行有一个数字(-231~231)。
数据输出
对于每组输入数据,输出一行一个数字,表示众数。
如果存在多个解,只需输出值最小的众数即可。
算法思路:
首先用快速排序算法排序数组,找到当前数组的中位数及其位置,然后把在数组中与中位数相同的数字向它靠拢,就可以统计中位数的个数。
现在数组已经被中间这些相等的数字分开了。
那么递归条件就有了。
如果中位数的个数比它左边这段短,那么说明左边有可能找到更多的,所以递归继续。
反之,如果左边这段数的长度比较短,那么就没必要继续递归。
对右边那段数据使用同样的策略。
实验三
集合划分问题
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},{2,3}},
{{1,2,3},{4}},
{{1,2,4},{3}},
{{1,3,4},{2}},
{{2,3,4},{1}},
{{1,2,3,4}}
其中,集合{{1,2,3,4}}由1个子集组成;集合{{1,2},{3,4}},{{1,3},{2,4}},{{1,4},{2,3}},{{1,2,3},{4}},
{{1,2,4},{3}},{{1,3,4},{2}},{{2,3,4},{1}}由2个子集组成;集合{{1,2},{3},{4}},{{1,3},{2},{4}},{{1,4},
{2},{3}},{{2,3},{1},{4}},{{2,4},{1},{3}},{{3,4},{1},{2}}由3个子集组成;集合{{1},{2},{3},{4}}由4个子集组成。
给定正整数n和m,计算出n个元素的集合{1,2,...,n}可以划分为多少个不同的由m个非空子集组成的集合。
输入
输入的第1行是元素个数n和非空子集数m
输出
输出计算的不同的由m个非空子集组成的集合数
样例输入
43
样例输出
6
实验四:
整数因子分解问题
大于1的正整数n可以分解为:
n=x1*x2*…*xm。
例如,当n=12时,共有8种不同的分解式:
12=12;12=6*2;12=4*3;12=3*4;12=3*2*2;12=2*6;12=2*3*2;12=2*2*3。
对于给定的正整数n,计算n共有多少种不同的分解式。
Input
输入数据只有一行,有1个正整数n(1≤n≤2000000000)。
Output
将计算出的不同的分解式数输出。
SampleInput
12
SampleOutput
8
二、实验内容与思想设计
1、实验一的思想
核心算法思想:
分治思想在2kx2k个方格组成的棋盘中用到的L型骨牌恰有(4k-1)/3个。
为解决该问题的算法思想。
从分治的思想易得到需将问题微型化,于是我们将棋盘平均分成四个相似的棋盘。
若特殊方格恰在图示的第一块区域,为了符合分治的思想我们需要将其他三部分转化成同样具有特殊方格的棋盘,依次递归知道棋盘为1x1的规模即可解决问题。
我的理解:
倘若特殊方格在第一象限的区域内。
按照算法的思想将其余三块也转化成类似问题后一次递归,最终将会把2、3、4这三个格子留下来其余的格子会被全部覆盖掉。
而2、3、4着三个位置也恰好可以防止一个骨牌上去,最终就会完成整个问题的求解。
2、实验二的思想
首先用快速排序算法排序数组,找到当前数组的中位数及其位置,然后把在数组中与中位数相同的数字向它靠拢,就可以统计中位数的个数。
现在数组已经被中间这些相等的数字分开了。
那么递归条件就有了。
如果中位数的个数比它左边这段短,那么说明左边有可能找到更多的,所以递归继续。
反之,如果左边这段数的长度比较短,那么就没必要继续递归。
对右边那段数据使用同样的策略。
3、实验三的思想
递归思想在n和k较小的时候,问题显得比较简单,但当n和k增大后,问题异常复杂。
此问题有一定的递归问题特点,用集合{1,2,3}划分为2个子集(n=3,k=2)来说明。
显然划分为一下2个子集有3中方法:
{{1,2},{3}}{{1,3},{2}}{{2,3},{1}}按照这个例子,我们可以将三个数字划分为2部分来看,前面的元素1和2为第一部分,第三个元素3为第二部分。
12|3如上所示,把12这部分先按照要求分为2个子集,在分别把3放入每一个子集一次,组成的就是2个划分。
还有一种可能就是3单独成为一个子集,那么12的部分分成2-1个子集组成的划分就可以了。
当n=3且k=2时,能够产生的划分总数是2*1+1=3种。
包含n个元素的集合进行k划分,假定总的划分次数为F(n,k),则其所有的划分可以由kF(n-1,k)和F(n-1,k-1)得到,前者是指将集合的前n-1个元素划分成k个子集,则将第k个元素可以加入其中的任一个子集形成一个新的划分,后者是指集合的前n-1个元素划分成k-1个子集,则第k个元素作为一个单独的元素组成一个子集形成k划分。
递归关系:
F(n,k)=k*F(n-1,k)+F(n-1,k-1)边界条件:
当k=1时,F(n,k)=1即分为一个子集,就是原集合,只有一种分发,包含所有元素。
当n=k时,F(n,k)=1即每个元素单独成为子集,只有一种分发,每个子集包含一个元素。
当n 4、实验四的思想 大于1的正整数n可以分解为: n=x1*x2*…*xm。 例如,当n=12时,共有8种不同的分解式: 12=12;12=6*2;12=4*3;12=3*4;12=3*2*2;12=2*6;12=2*3*2;12=2*2*3。 对于给定的正整数n,计算n共有多少种不同的分解式。 运用递归思想可以设计程序。 窗体顶端 三、测试结果 1、实验一测试结果如下图: 结果一: 结果二: 2、实验二的测试结果 3、实验三的测试结果 4、实验四的测试结果 四、实验心得 算法总体思想: 对这k个子问题分别求解。 如果子问题的规模仍然不够小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。 将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。 直接或间接地调用自身的算法称为递归算法。 用函数自身给出定义的函数称为递归函数。 由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。 在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。 这自然导致递归过程的产生。 分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。 通过以上返利学习分治策略设计技巧,熟悉了分治递归思想,进一步掌握递归算法的设计思想以及递归程序的调试技术。 在做实验的过程中理解这样一个观点: 分治与递归经常同时应用在算法设计之中。 五、附: 源程序 1、实验一棋盘覆盖问题程序 #include #include usingnamespacestd; intboard[100][100];//存放棋盘L型的标号数组; inttile=0;//L型骨牌号 intmain() { voidchessBoard(inttr,inttc,intdr,intdc,intsize);//棋盘的覆盖方法; voiddisplay(int*board,intsize);//棋盘覆盖图; intsize,dr,dc; cout<<"\t棋盘覆盖问题\n"; cout<<"2^k×2^k个方格变长size(size=2,4,8,16,32,64): "; cin>>size; cout<<"分别输入特殊块的行列下标dr,dc(0-"<<(size-1)<<"): "; cin>>dr>>dc; board[dr][dc]=-1; cout<<"棋盘覆盖图: \n"; chessBoard(0,0,dr,dc,size); inti,j; for(i=0;i { for(j=0;j cout< cout< } return0; } voidchessBoard(inttr,inttc,intdr,intdc,intsize) { if(size==1) return; intt=tile++;//L型骨牌号 ints=size/2;//分割棋盘 //覆盖左上角子棋盘 if(dr 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 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 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、实验二众数问题程序 #include #include usingstd: : cout; usingstd: : endl; usingstd: : cin; usingstd: : map; //定义一个map类型,键为数,值为其重复次数 map typedefmap : const_iteratorIterator; //计算的函数,参数为一个数组和其长度 Iteratorcalc(int*list,intlen) { for(inti=0;i { ++s_map[list[i]]; } //找出众数,即出现次数最多的数 Iteratortimes=s_map.begin(); Iteratoritr; for(itr=s_map.begin();itr! =s_map.end();++itr) { if(times->second times=itr; } returntimes; } intmain() { intsize; cin>>size;//输入多重集S元素的个数 int*ps=newint[size]; for(inti=0;i { cin>>ps[i]; } Iteratoritr=calc(ps,size); cout< < } 3、实验三集合划分问题程序 #include"stdio.h" intF(intx,inty) { if(y==1) return (1); elseif(x==y) return (1); else return(F(x-1,y-1)+y*F(x-1,y)); } intmain() { inti,j; intsum=0; intF(intx,inty); printf("请输入集合的元数: "); scanf("%d",&i); for(j=1;j<=i;j++) sum=sum+F(i,j); printf("%d元集合的划分总数是: %d\n",i,sum); } 4、实验四整数因子分解问题 #include usingnamespacestd; intnum=0;//计数器 //递归求数的分解的个数 voidsolve(longn){ if(1==n){ num++; }elseif(1 for(inti=n;i>=2;i--){ doubleresult=n*1.0/i; if(result==(long)result){ solve(n/i); } } } } intmain(){ longn; std: : cin>>n; solve(n); std: : cout< return0; } 如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。 copyright@ 2008-2022 冰点文档网站版权所有 经营许可证编号:鄂ICP备2022015515号-1=tc+s)//特殊方格在此棋盘中