当前位置:文档之家› 课程设计报告

课程设计报告

课程设计报告
题目:(串数问题)一个A和两个B一共可以组成三种字符串:“BBA”、“ABB”、“BAB”。

给定若干字母和他们对应的个数,计算一共可以组成多少个不同的字符串。

要求:
输入:每组测试数据分两行,第一行为n(1<=n<=26),表示不同字母的个数,第二行为n个数A1,A2,...,An(1<=Ai<=12),表示每种字母的个数.测试数据以n=0为结束.
输出:对于每一组测试数据,输出一个m,表示一共有多少种字符串。

例如:
Sample Input
2
1 2
3
2 2 2
Sample Output
3
90
1、问题分析和任务定义
从问题可知,判断不同的字母可以组成多少不同的字符串,首先要确定有几种字母,然后要确定每种字母出现的次数。

但是,每种字母出现的次数是不定的,所以要确定以哪一种存储结构来保存这些字母出现的次数。

根据排列组合的知识可知,出现的字符串的种类数由字母总的个数(包括重复的字母)和每一种字母重复的次数决定。

例如,有m个A和n个B,那么就有(m+n)!/(n!*m!)个不同的字符串。

2、数据结构的选择和概要设计
由实际情况可以知道,英语字母只有26个,所以可以用顺序表来存储每种字母重复出现的次数和所有字母出现的次数。

顺序表的结构类型如下所示:
#define maxlen 26
typedef struct
{
int data[maxlen];
int last;
}Sequenlist;
我们从下标为0的数组元素开始记录字母重复的次数,每个字母出现的次数最多不超过12次,否则程序提示重新输入,直至输入的数据符合要求,程序才会继续向下执行。

3、详细设计和编码
此函数有一个主函数main()和两个子函数fact()和result()。

fact()主要实现阶乘的运算,传递给它一个数值,它就可以计算出这个数的阶乘是多少,然后返回给主函数。

result()的功能是计算出最终的结果,即共有多少种不同的字符串。

首先,定义一个变量m用于存储用户输入的字母种类数,然后判断m的值是否符合实际,如果不符合实际,就提示用户重新输入,如果用户输入的数值不正确,则不进行下一步操作。

printf("请输入字母的种类数:");
scanf("%d",&m);
if(m==0)
break;
//如果输入的种类数小于1或大于26,提醒重新输入
while(m<1||m>26)
{
printf("请重新输入字母的种类数:");
scanf("%d",&m);
}
用顺序表中的data[i]分量来记录每种字母重复出现的次数,用分量last记录字母总的次数p->last=p->last+p->data[i]。

然后再根据排列组合的公式带到相应的子函数中计算阶乘值sum1=sum1*fact(p->data[i])、fact(p->last)。

由于程序要能够实现连续输入数据的功能,所以程序中用到了while循环,结束条件是当输入字母种类为0时结束,即当m==0是程序结束,由break跳出循环。

为了避免循环后p->last的累加和sum1值的累乘,所以在循环最后令p->last =0、sum1=1。

两个子函数的功能非常简单,只要实现对阶乘的计算和除法运算即可。

即主函数调用fact()时给它一个参数,fact()函数就可以求出这个参数的阶乘值并返回给函数。

主函数传递给result()函数两个值,result()即可求出这两个数的商并返回给主函数。

int fact(q)
{
int j,sum2=1;
for(j=1;j<=q;j++)
{
sum2=sum2*j;
}
return sum2;
}
//除法函数
int result(int a,int b)
{
return a/b;
}
4、上级调试过程
由如下截图可知,第二个显示的结果是错误的。

因为在循环中p->last进行了多次累加、sum1进行了多次累乘,所以导致第二次输入的结果值有很大的偏差。

经修改后出现了正确的结果。

5、测试结果及其分析
测试数据1:
4
1 2 2 1
输出结果:180
由程序运行结果可知,有四种字母,第一种字母出现一次,第二种字母出现两个,第三种字母出现两个,第四种字母出现一个,总共有六个字母,由排列组合公式可知,6!=720,2!=2,所以720/(2*2)=180,显示结果正确。

测试数据2:
2
1 2
3
2 2 2
输出结果:
3
90
同理,由排列组合知识可以知道,程序输出结果正确。

测试数据3:
32//错误输入,程序提示重新输入
2
3 4
输出结果:35
同理,由排列组合知识可以知道,程序输出结果正确。

测试数据4:
2
3 13//输入结果错误,提示重新输入 1
输出数据:4
同理,由排列组合知识可以知道,程序输出结果正确。

6、用户使用说明
(1)每组测试数据分两行,第一行为n(1<=n<=26),表示不同字母的个数,第二行为n个数A1,A2,……An(1<=Ai<=12),表示每种字母的个数,测试数据以n=0为结束。

(2)对于每一组测试数据,输出一个m,表示一共有多少种字符串。

(3)输入数据不符合要求时,程序会提示重新输入,请按照提示重新输入数值。

7、参考文献
[1]作者:王昆仑、李红书名:《数据结构与算法》出版地:北京出版商:中国铁道出版社出版时间:2006年7月第一版
8、附录
#include "stdio.h"
#define maxlen 26
//定义顺序表
typedef struct
{
int data[maxlen];
int last;
}Sequenlist;
int fact(int q);//用于计算数的阶层
int result(int a,int b);//用于计算最终的结果
void main()
{
//定义运算中需要的变量
int m,i,j,r=0;
int sum1=1;
int data1[12];
Sequenlist l,*p;
p=&l;
p->last=0;
while(12)
{
//确定字母的种类数
printf("请输入字母的种类数:");
scanf("%d",&m);
if(m==0)
break;
//如果输入的种类数小于1或大于26,提醒重新输入
while(m<1||m>26)
{
printf("请重新输入字母的种类数:");
scanf("%d",&m);
}
//确定每一种字母出现的次数
printf("请输入每种字母的个数:");
for(i=0;i<m;i++)
{
scanf("%d",&p->data[i]);
//如果每种字母出现的次数小于1次或大于12次,提醒用户重新输入
while(p->data[i]<1||p->data[i]>12)
{
printf("请重新输入每种字母的个数:");
scanf("%d",&p->data[i]);
}
p->last=p->last+p->data[i];//记录所有字母出现的次数总和
sum1=sum1*fact(p->data[i]);
}
data1[r]=result(fact(p->last),sum1);
p->last =0;
sum1=1;
r++;
}
for(j=0;j<r;j++)
{
printf("总共有%d个不同的字符串!\n",data1[j]);
}
}
//求阶乘的函数
int fact(q)
{
int j,sum2=1;
for(j=1;j<=q;j++)
{
sum2=sum2*j;
}
return sum2;
}
//除法函数
int result(int a,int b) {
return a/b;
}。

相关主题