环形石子合并问题
1. 代码示例
下面展示 程序代码
。
#include<stdio.h>
#define N 100
/*
*求合并过程中
*最少合并堆数目
*/
int MatrixChain_min(int p[N],int n)//p[N]石子数,n石子堆数
{
int m[N][N]; //定义二维数组m[i][j]来记录i到j的合并过成中最少石子数目(石子积分)
int min=0;
for(int g = 1;g<=n;g++)
m[g][g]=0; //当一个单独合并时,m[i][i]设为0,表示没有积分。
for(int i=1;i<=n-1;i++)//当相邻的两堆石子合并时,此时的m很容易可以看出是两者之和。
{
int j=i+1;
m[i][j]=p[i]+p[j];
}
for(int r=3; r<=n;r++)//当相邻的3堆以及到最后的n堆时,执行以下循环(r表示考虑到了多堆石子合并的所有情况)
for(int i=1;i<=n-r+1;i++)//i表示开始的那一堆,j表示最后的那一堆
{
int j = i+r-1; //j总是距离i r-1的距离
int fin=0;
for(int b=i;b<=j;b++)//当i到j堆石子合并时最后里面的石子数求和得fin(fin是所有的石子数)
fin+=p[b];
// 此时m[i][j]为i~j堆石子间以m[i][i]+m[i+1][j]+fin结果,这是其中一种可能,不一定是最优【】???
//要与下面的情况相比较
m[i][j] = m[i+1][j]+fin;//最初的积分情况
//除上面一种组合情况外的其他组合情况
for(int k=i+1;k<j;k++)//进行比较
{
int t=m[i][k]+m[k+1][j]+fin;//后来情况的积分
if(t<m[i][j])
m[i][j] = t;
}
}
//最终得到最优解
min=m[1][n]; //最小的情况赋值给min
return min;
}
/*
*求合并过程中
*最多合并堆数目
**/
int MatrixChain_max(int p[N],int n)
{
int m[N][N];
int max=0;
//一个独自组合时
for(int g = 1;g<=n;g++)
m[g][g]=0;
//两个两两组合时
for(int i=1;i<=n-1;i++)
{
int j=i+1;
m[i][j]=p[i]+p[j];
}
for(int r=3; r<=n;r++)
for(int i=1;i<=n-r+1;i++)
{
int j = i+r-1;
int sum=0;
for(int b=i;b<=j;b++)
sum+=p[b];
m[i][j] = m[i+1][j]+sum;
for(int k=i+1;k<j;k++)
{
int t=m[i][k]+m[k+1][j]+sum;
if(t>m[i][j])
m[i][j] = t;
}
}
max=m[1][n];
return max;
}
int main()
{
int stone[N];//每堆石子数
int min=0;//最小的分初始化
int max=0;//最大的分初始化
int n;//石子堆数
printf("请输入石子堆数:");
scanf("%d",&n);
for(int i=1;i<=n;i++){
printf("请输入第%d堆石子数:",i);
scanf("%d",&stone[i]);
}
min= MatrixChain_min(stone,n);//传到子函数
max= MatrixChain_max(stone,n);//传到子函数
//因为题目要求圆的原因,要把所有情况都要考虑到,总共有n种情况。
for(int j=1;j<=n-1;j++)
{
int min_cache=0;//积分最小情况
int max_cache=0;//积分最大情况
int cache= stone[1];//
for(int k=2;k<=n;k++)
{
stone[k-1]=stone[k];
}
stone[n]=cache;//
min_cache= MatrixChain_min(stone,n);//
max_cache= MatrixChain_max(stone,n);//
if(min_cache<min)
min=min_cache;//
if(max_cache>max)
max=max_cache;//
}
printf("最小得分:%d\n",min);
printf("最大得分:%d\n",max);
return 1;
}
2. 产生的错误
(1)循环输入石子堆数代码错误
错误代码如下所示:
更正后:
(2)代码运行结果错误
在起初代码运行成功时,进行了算法测试,分别输入1堆、2堆、3堆、5堆石子来验证算法准确性。
1堆石子运行结果:
2堆石子运行结果:
3堆石子运行结果:
显而易见,2堆和3堆石子运行结果均错误。
感悟与体会
通过本次代码的编写与实现,我从中感悟到了很多。一个高效的程序不仅需要编程技巧,更需要合理的数据组织和清晰高效的算法。通过对课程的理论学习与实践,我掌握了许多经典的算法思想,思维创新能力和实践能力得到了有效的提高,并且一题多解的情况让我对不同的算法有了更加深刻的认识。本次算法实验题让我深刻感悟到了动态规划法的魅力,同时在程序设计过程中遇到的为你也会让我认识到自己的不足,实际实践之后,这些知识在我们今后的学习中将会得到更深层次的理解与应用。