合并石子 四边形不等式优化

Posted 玥~endlessly~vast

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了合并石子 四边形不等式优化相关的知识,希望对你有一定的参考价值。

题目描述

  有一排石子,共n 堆。现要将石子有次序地合并成一堆。规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试设计一个算法,计算出将n堆石子合并成一堆的最小得分。

题解

  首先由直接动态规划的方法来做,即 

for(int i=1;i<=n;i++)
    for(int j=i;j<=n;j++)
        for(int k=i;k<=j;k++)
            {
               f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+cost[j]-cost[i-1]);
        
}   

  但是如果N的值超过了3000的话,这个算法就明显会爆炸的,所以我们应当采取一定的优化,经过计算我们可以发现这个题目是满足四边形不等式的,这里所用的优化呢是四边形不等式优化。

  我们定义阶段为区间长度len,状态为f[i][j]合并i到j的最小费用。

  注意:因为我们的阶段决定了,在计算s[i][j]时,s[i][j-1]和s[i+1][j]都已经计算出来了

代码

//FZOJ1555 合并石子(求最小值)四边形不等式优化 
#include<bits/stdc++.h>
using namespace std;
int f[101][101],s[101][101],a[101],sum[101],q;
int main()
{
    int i,j,k,n,len,q;
    scanf("%d",&n);
    memset(sum,0,sizeof(sum));
    memset(f,60,sizeof(f));
    memset(s,0,sizeof(s));
    for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }    
    for(i=1;i<=n;i++)
        {
            f[i][i]=0;
            s[i][i]=i;
        }
    for(len=1;len<n;len++)
        for(i=1;i<=n-len;i++)
            {
                j=i+len;
                q=sum[j]-sum[i-1];
                for(k=s[i][j-1];k<=s[i+1][j];k++)
                    {
                        if(f[i][j]>f[i][k]+f[k+1][j]+q)
                            {
                                f[i][j]=f[i][k]+f[k+1][j]+q;
                                s[i][j]=k;
                            }
                    }
            }
    printf("%d\n",f[1][n]);
    return 0;
}

 

以上是关于合并石子 四边形不等式优化的主要内容,如果未能解决你的问题,请参考以下文章

石子合并问题(四边形不等式DP优化)

四边形不等式(石子合并)

51nod - 1022四边形不等式优化DP

[dp专题-四边形不等式优化]51nod 1022

51Nod 1021~1023 石子合并 (逐步加强版) dp

四边形不等式COGS1658- [HZOI 2014] 合并石子