运行结果为:
可以看出Distance数组中几乎所有的元素都溢出了。
检查出来是为未初始化造成的。
实验二中的过程比较简单,课件中已经给出了比较详细的算法,因此编写过程中并没有出现什么大的问题,只有一些小的书写方面和终止条件考虑不当的错误。
在最后的结果中,发现每当工程数大于资金数时,就会出现以下结果:
收入的总资金一直为负,而工程i的投入资金都显示正确,检查总资金total的求值过程,在最后可以看出,由于表中并没有投入资金为0时,并没有收入,这里出现错误,在求total的过程中应当排除中这种情况,添加语句以下语句,结果正确,错误被更正。
if(result[i]>0)total+=profit[i][result[i]-1];
在这里,还有一个常见的错误,就是忘记输入时在变量前面加上符号&,使程序出现中断。
第三部分:
实验结果分析(可加页)
实验一:
1.下组数据是书上的一组例题,运行结果显示正确,给出了最短路径和路径长度。
2.在上个输入的基础上,将结点之间的代价反过来,即i->j的代价与j->i的代价互换后,依然以1结点作为开始,路程反过来,由下图可示,输出结果正确。
3.该组数据也是书上的,但是开始的结点处不同。
给出了最短路径和路径长度。
一、时间复杂性分析:
由于这里涉及到填表,这里的复杂性只与数组的大小有关,因此没有情况好坏的差别,故这里考虑平均情况下,算法的时间复杂性为O(2n)。
和蛮力法相比,动态规划法求解TSP问题,把原来的时间复杂性是O(n!
)的排列问题,转化为组合问题,从而降低了算法的时间复杂性,但它仍需要指数时间。
二、空间复杂度分析:
这里的填表的过程需要的空间与数据的个数有关即为n,这里的Distance数组的纵坐标为0~2n-1,故空间的复杂度为O(2n)。
三、算法功能:
该算法的功能只要是解决JSP问题,寻找要从某地出发,途径所有的结点最后回到出发地所需的最小代价和路程,这个算法的计算过程就是通过将所有下个可能的结点的代价算出来求出最小值来填表。
实验二:
1.工程数比资金少的情况下,运行结果为:
2.工程与资金相同的情况下,运行结果下:
3.工程比资金多的情况下,运行结果如下:
可以看出以上结果均正确。
动态规划递推关系式:
V(i,0)=V(0,j)=0
一、时间复杂性分析:
平均情况下:
在该段程序中,for循环嵌套最多的是对决策表进行赋值的时候,里面包含三个for循环,运行次数为N*A*A!
,因此时间复杂度为O(n!
)。
二、空间复杂度分析:
该程序不需要临时存储空间,这里他的数据全部存在定义的几个数组中,可以看出空间复杂度为0(N*A)。
三、算法功能:
该算法主要表达的是填动态规划表的方法,通过不断填表来满足后续数据的求解。
第三部分:
实验小结、建议及体会
实验一中,我感觉我用的方法太复杂了,在其中使用了许多的for、while循环和ifelse条件判断,而且在编写的过程中花费了很多的时间,感觉有些并不理解自己写的东西,再者就是有时写着写着就不知道写到哪儿了。
这反映了我的一个问题,对程序没有事先考虑好以及没有理解好,这样写起来就很不顺利。
对递归的掌握也不是很好,但是在编写这个程序的过程中,对动态规划法确实有了一些深的理解,还是要多动手,使程序的可读性提高。
至于实验二,就是一个变相0/1的背包问题。
最开始对题目的理解出现了偏差,使问题复杂化了,解决这个地方也花了不少时间,还是应该多请教他人,不能固执地钻牛角尖。
附录
实验一:
#include
#include
intm,n,time=0,Distance[6][64],start,routine[7],distance[6][6],number[64],array[64][6];
intfindCompare(inti,intj,intk){//找到当要分解一个Distance[][]时,求的对应一个distance[][]的Distance[][]的纵坐标
intx=0,y,initial=0;
while(number[x]!
=number[j]-1)x++;
while(initial==0){
y=0;
for(intl=0;lif(array[x][l]==array[j][l]||l==k)
y++;}
if(y==n)initial=1;
elsex++;}
return(x);
}
voidgetRoutine(inti,intj,intinitial){//确定得到最小路径值的路径
intk,x;
switch(initial){
case0:
k=1;
while(distance[0][k]+Distance[k][m-k-1]!
=Distance[i][j]&&kif(k+1!
=start)
routine[1]=k+1;
elseroutine[1]=1;
i=k;j=m-k-1;
case1:
time++;
for(k=0;kif(array[j][k]==1){
x=findCompare(i,j,k);
if(Distance[i][j]==distance[i][k+1]+Distance[k+1][x]){
if(k+1!
=start)
routine[time+1]=k+2;//time=1,k=1
elseroutine[time+1]=1;}
}
}
if(time+1routine[n-1]=1;
getRoutine(k+1,x,1);
if(time==n-1){
j=0;
for(i=1;i<=n;i++)
j+=i;
for(i=0;ij=j-routine[i];}
routine[n-1]=j;}}
}
voidmain(){
intinitial,x,i,j,t,k;
printf("请输入结点个数:
");
scanf("%d",&n);
m=pow(2,n)/2;
printf("请依次输入结点之间的代价(以矩阵的形式输入,本结点之间的代价写0):
");
for(i=0;iprintf("\n");
routine[i]=0;
for(j=0;jscanf("%d",&distance[i][j]);}
printf("\n");
printf("请输入想作为开始的结点编号(从1开始):
");
scanf("%d",&start);
routine[n]=start;
routine[0]=start;
for(i=0;it=distance[0][i];
distance[0][i]=distance[start-1][i];
distance[start-1][i]=t;}
for(j=0;jt=distance[j][0];
dista