版权声明:最后一年,加油~ https://blog.csdn.net/zzti_xiaowei/article/details/87114915
[题目]
:
n堆石子摆成一条线。现要将石子有次序地合并成一堆,规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。计算将n堆石子合并成一堆的最小代价。
[普通解法]
:
状态转移方程:
表示区间
上的最优值,
表示转移时付出的代价。
复杂度:O(n3)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int Max_n=1100;
int n;
int a[Max_n],sum[Max_n];
int dp[Max_n][Max_n];
int main()
{
scanf("%d",&n);
sum[0]=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
// 从小区间向大区间进行地推
for(int d=1;d<n;d++){ //先枚举区间长度
for(int i=1,j;(j=i+d)<=n;i++){ //再枚举区间起点
dp[i][j]=inf;
for(int k=i;k<j;k++)
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
dp[i][j]+=sum[j]-sum[i-1];
}
}
printf("%d\n",dp[1][n]);
return 0;
}
[四边形不等式优化]:
对于一般方程:
如果
函数满足区间单调性和四边形不等式性质,则
函数也满足四边形不等式性质,具有决策单调性。
- 决策单调性:
定义 为 取得最优值时对应的决策点(即下标),则s(i,j-1)≤s(i,j)<s(i+1,j)
。 - 优化方程:
f(i,j)=opt{f(i,k)+f(k,j)}+w(i,j) s(i,j-1)≤k≤s(i+1,j)
,复杂度:O(n2)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int Max_n=1100;
int n;
int a[Max_n],sum[Max_n];
int s[Max_n][Max_n],dp[Max_n][Max_n];
int main()
{
scanf("%d",&n);
sum[0]=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
s[i][i]=i;
}
// 从小区间向大区间进行地推
for(int d=1;d<n;d++){ //先枚举区间长度
for(int i=1,j;(j=i+d)<=n;i++){ //再枚举区间起点
dp[i][j]=inf;
for(int k=s[i][j-1];k<=s[i+1][j];k++)
if(dp[i][k]+dp[k+1][j]<dp[i][j]){
dp[i][j]=dp[i][k]+dp[k+1][j];
s[i][j]=k;
}
dp[i][j]+=sum[j]-sum[i-1];
}
}
printf("%d\n",dp[1][n]);
return 0;
}