资深守护
求大佬帮忙
一下核心代码:
while(1)
{
cin>>n;
memset(sum,0,sizeof(sum));
if(n==0)
break;
for(int i=1;i<=n;++i)
{
cin>>data[i];
sum[i]+=sum[i-1]+data[i];
}
memset(f,15,sizeof(f));
for(int i=1;i<=n;++i)
{
f[i][i]=0;
}
for(int d=1;d<n;++d)
{
for(int i=1;i<=n-d;++i)
{
int j=i+d;
for(int k=i;k<j;++k)
{
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1]);
}
}
}
cout<<f[1][n]<<endl;
}
必采纳
蟹蟹
赵毅恒在2018-02-27 19:13:30追加了内容
能不能跟我说说哪里错了,抄来的东西我是不会采纳的
高级光能
首先,列出石子 进行观察。A[i]为该堆中的石子个数
1.□ 2.□□ 3.□□□ 4.□□□□ 5.□□□□□
1.若石子有1堆,则无需合并,花费为0
2.若石子有2堆,则合并二者,花费为A[0]+A[1]
3.若石子有3堆,则有2种情况,①先合并A[0]、A[1]再与A[2]合并 ②先合并A[1]、A[2]再与A[0]合并
4.若石子有4堆,则有3种情况,...............
总之,在n堆中,有n-1种情况,而最后一次合并总是以某两堆合成一堆为结果。
即可将n堆划分成A[0...k] 与 A[k+1...n-1]合并,
而A[0...k] 与 A[k+1...n-1]已是最优花费,由各自向下分解所得。
(递归思想,但由于此次是二维的,即符合动态规划)
————————————————————————————————————
假设有5堆石子,则A[0...k] 与 A[k+1...n-1]的长度堆数可能为 1、4 2、3 3、2 4、1
只要其各自已为最优花费。
以上为递推向下的逻辑,在动态规划是由下而上,即5堆石子 需要长度为 2 3 4 的石子最优花费
如图。
然后开始分析算法过程,首先,最外层循环 控制石子堆长度(len=2 to n),因为只有1堆时无需下续步骤
接着第二层循环,确定石子堆的起始堆号(i=0 to n-len)即为图中的下划线个数。
继续分析,发现还需要一层循环控制更新 A[0...k] 与 A[k+1...n-1]的花费price (k=i to j-1)
确定无遗漏后,开始编写代码过程,如下。
(注意,花费是每两两合并完的石子数依次相加,所以最后一次合并为合并堆数的总石子量)
——————————————————————————————————————————————、
由sum[i][j]表示第i堆石子到第j堆石子全部合并的总石子量。dp[i][j]为第i堆石子到第j堆合并的花费(随着动态规划的进行,会越来越越接近最优花费)dp[i][i]=0 (本身无需合并,不需花费)
即若仅两堆石子合并 则dp[i][j]=dp[i][i]+dp[j][j]+sum[i][j] = 0+0+sum[i][j]
以下用一维sum[n]进行存储,sum[i][j]=sum[j]-sum[i-1] (i!=0), sum[i][j]=sum[j] (i==0)