区间DP 原理和套路

区间DP

题目是

有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1]。问安排怎样的合并顺序,能够使得总合并代价达到最小。

分析

区间DP 原理和套路_第1张图片

  • f[i,j]表示所有所有将第i堆到第j堆石子合并成一堆石子的合并方式
  • 枚举【i,j】的长度从 2 - n
    • 第i堆到第j堆石子合并成一堆石子的合并方式,一共三步
      • 1 第i - k 凑成一堆最小值
      • 2 第 k+1 - j 凑成一堆的最小值
      • 3 两堆合起来。就是 【i,j】所有数之和。可以用前缀和表示。

区间DP 原理和套路_第2张图片

#include
using namespace std;

const int N=310,INF=0x3f3f3f3f;
int f[N][N];
int s[N];
int n;

int main(){
    cin>>n;
    memset(f,INF,sizeof(f));     //记得初始化
    for(int i=1;i<=n;i++){
         cin>>s[i];
         f[i][i]=0;             //初始化
    }
    for(int i=1;i<=n;i++) s[i]+=s[i-1]; // 前缀和

    for(int len=2;len<=n;len++){ // 区间划分
        for(int l=1;l+len-1<=n;l++){
            int r=l+len-1;
            for(int k=l;k<r;k++){
                f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);
            }    
        }
    }
    cout<<f[1][n]<<endl;
    return 0;
}

你可能感兴趣的:(算法,DP)