算法设计与分析实验.docx

上传人:b****1 文档编号:12470487 上传时间:2023-04-19 格式:DOCX 页数:19 大小:18.36KB
下载 相关 举报
算法设计与分析实验.docx_第1页
第1页 / 共19页
算法设计与分析实验.docx_第2页
第2页 / 共19页
算法设计与分析实验.docx_第3页
第3页 / 共19页
算法设计与分析实验.docx_第4页
第4页 / 共19页
算法设计与分析实验.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

算法设计与分析实验.docx

《算法设计与分析实验.docx》由会员分享,可在线阅读,更多相关《算法设计与分析实验.docx(19页珍藏版)》请在冰豆网上搜索。

算法设计与分析实验.docx

算法设计与分析实验

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;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1