算法设计与分析实验.docx
- 文档编号:9547065
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:19
- 大小:19.30KB
算法设计与分析实验.docx
《算法设计与分析实验.docx》由会员分享,可在线阅读,更多相关《算法设计与分析实验.docx(19页珍藏版)》请在冰豆网上搜索。
算法设计与分析实验
IntegerFactorization
Description
问题描述:
大于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
程序如下:
#include
#include
structDP
{
intnum;
intsum;
}d[50000]={0};
intmax=0;
voidqsort(intlow,inthigh,structDPkey[])
{
inti=low,j=high;
structDPtag=key[i];
if(i { do { while(tag.num if(i { key[i]=key[j]; i++; while(tag.num>=key[i].num&&i if(i { key[j]=key[i]; j--; } } }while(i key[i]=tag; qsort(low,j-1,key); qsort(i+1,high,key); } } intdfs(intleft) { inti,p; intl,r,m; intcount=0; l=0;r=max; while(l<=r) { m=(l+r)>>1; if(d[m].num } p=l;if(d[p].sum)returnd[p].sum; for(i=1;i<=d[i].num;i++) { if(left%d[i].num==0)count+=dfs(left/d[i].num); } d[p].sum=count; returncount; } intmain(void) { inti,j,tmp; intn; scanf("%d",&n); tmp=sqrt(n); for(i=1;i<=tmp;i++) { if(n%i==0) { d[max].num=i;max++; d[max].num=n/i;max++; } }max--; qsort(0,max,d); d[0].sum=1; printf("%d\n",dfs(n)); return0; } 比赛安排 Description 设有2^n(n<=6)个球队进行单循环比赛,计划在2^n–1天内完成,每个队每天进行一场比赛。 设计一个比赛的安排,使在2^n–1天内每个队都与不同的对手比赛。 例如n=2时的比赛安排: 队1234 比赛1==23==4一天 1==32==4二天 1==42==3三天 Input 输入由多组测试数据组成。 每组测试数据输入一个正整数代表题目中的n。 Output 对应每组输入,输出如样例所示。 <1>1-2,3-4表示第一天1队与2队,3队与4队比赛 SampleInput 2 SampleOutput <1>1-2,3-4 <2>1-3,2-4 <3>1-4,2-3 程序如下: #include inta[80][80]; voidcopy(intn) { intm,i,j; m=n/2; for(i=1;i<=m;i++) for(j=1;j<=m;j++) { a[i][j+m]=a[i][j]+m; a[i+m][j]=a[i][j+m]; a[i+m][j+m]=a[i][j]; } } voidwz(intn) { if(n==1){a[1][1]=1;return;} else wz(n/2); copy(n); } intmain() { intn,i,j,m,f,k; while(scanf("%d",&n)! =EOF){ k=1; for(i=0;i k*=2; wz(k); m=0; for(j=2;j<=k;j++){ m++;f=1; for(i=1;i<=k;i++) { if(a[i][j]! =0){ if(f) {printf("<%d>%d-%d",m,i,a[i][j]);f=0;} else printf(",%d-%d",i,a[i][j]); a[a[i][j]][j]=0; } } printf("\n"); } } } 又是Hanoi塔问题 Description A、B、C是3个塔座。 开始时,在塔座A上有一叠共n个圆盘,这些圆盘自下而上,由大到小地叠在一起。 各圆盘从小到大编号为1,2,……,n,奇数号圆盘着蓝色,偶数号圆盘着红色,如图所示。 现要求将塔座A上的这一叠圆盘移到塔座B上,并仍按同样顺序叠置。 在移动圆盘时应遵守以下移动规则: 规则 (1): 每次只能移动1个圆盘; 规则 (2): 任何时刻都不允许将较大的圆盘压在较小的圆盘之上; 规则(3): 任何时刻都不允许将同色圆盘叠在一起; 规则(4): 在满足移动规则 (1)-(3)的前提下,可将圆盘移至A,B,C中任一塔座上。 按照上述四种规则移动过程中,如将圆盘从A柱移到B柱,则称B柱使用一次。 例如要将塔座A上2个圆盘,按上述四种规则移动到B柱,A柱使用0次,B柱使用2次,C柱使用1次。 试设计一个算法,统计用最少的移动次数将塔座A上的n个圆盘移到塔座B上并仍按同样顺序叠置时,A柱、B柱、C柱的使用次数。 编程任务: 对于给定的正整数n,编程计算最优移动方案时,A柱、B柱、C柱的使用次数。 Input 输入由多组测试数据组成。 每组测试数据的第1行是给定的正整数n。 Output 对应每组输入,输出的每一行由三个相互空格的正整数组成,分别表示塔座A的使用次数、塔座B的使用次数及塔座C的使用次数。 SampleInput 2 SampleOutput 021 程序如下: #include usingnamespacestd; classHanoi { private: intnumA,numB,numC; public: Hanoi(); voidMoveHanoi(intnum,charA,charB,charC); voidCaluater(charch1,charch2); voidDisplay(); }; Hanoi: : Hanoi() { numA=0; numB=0; numC=0; } voidHanoi: : Caluater(charch1,charch2) { if(ch2=='A') numA++; elseif(ch2=='B') numB++; else numC++; } voidHanoi: : MoveHanoi(intnum,charA,charB,charC) { if(num>0) { MoveHanoi(num-1,A,C,B); Caluater(A,B); MoveHanoi(num-1,C,B,A); } } voidHanoi: : Display() { cout< } intmain() { intnn; while(cin>>nn) { Hanoih; h.MoveHanoi(nn,'A','B','C'); h.Display(); } return0; } PermutationwithRepetition Description R={r1,r2,…,rn}是要进行排列的n个元素。 其中元素r1,r2,…,rn可能相同。 试设计一个算法,列出R的所有不同排列。 编程任务: 给定n以及待排列的n个元素。 计算出这n个元素的所有不同排列。 Input 输入由多组测试数据组成。 每组测试数据的第1行是元素个数n,1<=n<=500。 接下来的1行是待排列的n个元素。 Output 对应每组输入,将计算出的n个元素的所有不同排列输出,每种排列单独一行。 最后1行中的数是排列总数。 SampleInput 4 aacc SampleOutput aacc acac acca caac caca ccaa 6 程序如下: #include #include usingnamespacestd; intans; intok(charstr[],inta,intb) { if(b>a) for(inti=a;i if(str[i]==str[b]) return0; return1; } voidperm(charstr[],intk,intm) { inti; if(k==m) { ans++; for(i=0;i<=m;i++) { printf("%c",str[i]); } printf("\n"); } else { for(i=k;i<=m;i++) if(ok(str,k,i)) { swap(str[k],str[i]); perm(str,k+1,m); swap(str[k],str[i]); } } } intmain(intargc,char*argv[]) { charstr[1000]; intn; while(scanf("%d",&n)! =EOF) { ans=0; scanf("%s",str); perm(str,0,n-1); printf("%d\n",ans); } return0; } ProblemC: 整数划分问题 Description 将正整数n表示成一系列正整数之和: n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。 正整数n的这种表示称为正整数n的划分。 求正整数n的不同划分个数。 例如正整数6有如下11种不同的划分: 6; 5+1; 4+2,4+1+1; 3+3,3+2+1,3+1+1+1; 2+2+2,2+2+1+1,2+1+1+1+1; 1+1+1+1+1+1。 Input 输入包含n+1行; 第一行是一个整数n,表示有n个测试用例; 第2至n+1每行一个正整数。 Output 对应每组输入,输出正整数n的不同划分个数。 SampleInput 2 5 6 SampleOutput 7 11 程序如下: #include intsplit(intn,intm); intmain() { intk,i; inta[100]; scanf("%d",&k); for(i=0;i {scanf("%d",&a[i]); } for(i=0;i {printf("%d\n",split(a[i],a[i])); } } intsplit(intn,intm) { if((n<1)||(m<1))return0; if((n==1)||(m==1))return1; if(n if(n==m)returnsplit(n,m-1)+1; returnsplit(n,m-1)+split(n-m,m); } 双色Hanoi塔问题 Description A、B、C是3个塔座。 开始时,在塔座A上有一叠共n个圆盘,这些圆盘自下而上,由大到小地叠在一起。 各圆盘从小到大编号为1,2,……,n,奇数号圆盘着蓝色,偶数号圆盘着红色,如图所示。 现要求将塔座A上的这一叠圆盘移到塔座B上,并仍按同样顺序叠置。 在移动圆盘时应遵守以下移动规则: 规则 (1): 每次只能移动1个圆盘; 规则 (2): 任何时刻都不允许将较大的圆盘压在较小的圆盘之上; 规则(3): 任何时刻都不允许将同色圆盘叠在一起; 规则(4): 在满足移动规则 (1)-(3)的前提下,可将圆盘移至A,B,C中任一塔座上。 试设计一个算法,用最少的移动次数将塔座A上的n个圆盘移到塔座B上,并仍按同样顺序叠置。 编程任务: 对于给定的正整数n,编程计算最优移动方案。 Input 输入由多组测试数据组成。 每组测试数据的第1行是给定的正整数n。 Output 对应每组输入,输出的每一行由一个正整数k和2个字符c1和c2组成,表示将第k个圆盘从塔座c1移到塔座c2上。 SampleInput 3 SampleOutput 1AB 2AC 1BC 3AB 1CA 2CB 1AB 程序如下: #include intsplit(intn,intm); intmain() { intk,i; inta[100]; scanf("%d",&k); for(i=0;i {scanf("%d",&a[i]); } for(i=0;i {printf("%d\n",split(a[i],a[i])); } } intsplit(intn,intm) { if((n<1)||(m<1))return0; if((n==1)||(m==1))return1; if(n if(n==m)returnsplit(n,m-1)+1; returnsplit(n,m-1)+split(n-m,m); } 再次hanoi塔问题 Description 古老的汉诺塔问题是: 用最少的步数将N个半径互不相等的圆盘从l号柱利用2号柱全部移动到3号柱,在移动的过程中小盘要始终在大盘的上面。 现在再加上一个条件: 不允许直接把盘从l号柱移动到3号柱,也不允许直接把盘从3号柱移动到1号柱。 把盘按半径从小到大用1~N编号。 每种状态用N个整数表示,第i个整数表示i号盘所在的柱的编号。 则N=2时的移动方案为 (1,1)≥(2,1)≥(3,1)≥(3,2)≥(2,2)≥(1,2)≥(1,3)≥(2,3)≥(3,3) 初始状态为第O步,编程求在某步数时的状态。 Input 输入的第1行为整数T(1≤T≤50000),表示输入数据的组数。 接下来的丁行,每行有两个整数N,M(1≤N≤19,O≤M≤移动N个圆盘所需的步数)。 Output 输出共有T行。 对于每组输入数据,输出N个整数表示移动N个盘在M步时的状态,每两个数之间用一个空格隔开,行首和行末不要有多余的空格。 SampleInput 4 20 25 30 31 SampleOutput 11 12 111 211 程序如下: #include usingnamespacestd; intf[20],ans[20]; voidCompute(intn,intm,ints,intanx,intd) { if(n==0) return; if(m<=f[n-1]) { ans[n]=s; Compute(n-1,m,s,anx,d); return; } if(m<=2*f[n-1]+1) { ans[n]=anx; Compute(n-1,m-(f[n-1]+1),d,anx,s); return; } ans[n]=d; Compute(n-1,m-(2*f[n-1]+2),s,anx,d); return; } intmain() { intt,n,m,i; f[0]=0; for(i=1;i<=19;i++) f[i]=f[i-1]*3+2; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); Compute(n,m,1,2,3); for(i=1;i<=n;i++) printf(i==1? "%d": "%d",ans[i]); printf("\n"); } return0; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 设计 分析 实验