四边形不等式优化DP——石子合并问题 学习笔记

好方啊马上就要区域赛了连DP都不会QAQ

 

毛子青《动态规划算法的优化技巧》论文里面提到了一类问题:石子合并。

 

n堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。

求出将n堆石子合并成一堆的最小得分和最大得分以及相应的合并方案。

  设m[i,j]表示合并d[i..j]所得到的最小得分。

状态转移方程:

总的时间复杂度为O(n3)。

 

【优化方案】

四边形不等式:

m[i,j]满足四边形不等式

令s[i,j]=max{k | m[i,j]=m[i,k-1]+m[k,j]+w[i,j] }

m[i,j]满足四边形不等式可以推出函数s[i,j]的单调性,即s[i,j]≤s[i,j+1]≤s[i+1,j+1],     i≤j

优化的状态转移方程:

 

状态转移方程 m[i][j]=min{m[i][k-1]+m[k][j]}+w[i][j]}  (i<=k<=j)

如果w同时满足四边形不等式和区间单调关系,则m也满足四边形不等式

四边形不等式优化的作用:m满足四边形不等式 -> k最优决策单调性

 参考博客:http://blog.csdn.net/bnmjmz/article/details/41308919

 

  #include <string.h>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#define  LL long long
#define MOD 1000000007

using namespace std;

const int INF = 0x3f3f3f;
const int N = 1005;

int m[N][N]; //m[i,j]表示合并d[i..j]所得到的最小得分
int s[N][N];  //s[i,j]记录合并方案
int sum[N]; //前i个石子堆石子数量和
int n;

int solve()
{
    for(int i=1; i<=n; i++)
    {
        m[i][i] = 0;   //边界条件
        s[i][i] = i;
    }
        for(int l=1; l<n; l++)  //枚举 l = j' - i
        {
            for(int i=1; i+l<=n; i++)
            {
                int j = i+l;
                int tmp = INF;
                int k = 0;
                for(int div=s[i][j-1]; div<=s[i+1][j];div++) //最优决策的单调性
                {
                    if(tmp > m[i][div] + m[div+1][j] + sum[j] - sum[i-1] )
                    {
                        tmp = m[i][div] + m[div+1][j] + sum[j] - sum[i-1];
                        k = div;
                    }
                }
                m[i][j] = tmp;
                s[i][j] = k;
            }
        }
        return m[1][n];
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        sum[0] = 0;
        for(int i=1; i<=n; i++)
        {
            int a;
            scanf("%d",&a);
            sum[i] = sum[i-1] + a;
        }
        printf("%d
",solve());
    }
    return 0;
}
原文地址:https://www.cnblogs.com/smartweed/p/5914514.html