题目
282. 石子合并 - AcWing题库
AcWing 282. 石子合并(区间 DP 模版题详解分析) - AcWing
解释
- 状态表示:f(i,j)表示将i到j合并成一堆的方案的集合,属性为min
- 状态计算:i<j时,f(i,j)=min(f(i,k)+f(k+1,j)+s[j]-s[i-1] i=j时,f(i,i)=0
- 循环的第一层都为枚举区间长度,第二维是固定i的位置,确保每个状态都被计算到
- 最后答案即(1~n)的总区间,即f(1,n)
代码段
区间DP模板
for (int i = 1; i <= n; i++) {
dp[i][i] = 初始值
}
for (int len = 2; len <= n; len++) //区间长度
for (int i = 1; i + len - 1 <= n; i++) { //枚举起点
int j = i + len - 1; //区间终点
for (int k = i; k < j; k++) { //枚举分割点,构造状态转移方程
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j] + w[i][j]);
}
}
#include<iostream>
using namespace std;
const int N=310;
int a[N],s[N],f[N][N],n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[i]=a[i]+s[i-1];
}
for(int i=1;i<=n;i++)
f[i][i]=0;
for(int len=2;len<=n;len++)
for(int i=1;i+len-1<=n;i++)
{
int j=i+len-1;
f[i][j]=1e9;
for(int k=i;k<j;k++)
{
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
}
}
cout<<f[1][n]<<endl;
}