很显然可以把这个过程反过来计算贡献。
所以这就是道石子合并。
顺便打一下四边形不等式。
四边形不等式
对于方程形式如下的一类
动态规划问题(多是区间DP)
朴素的解法是
,但它实际上可以被优化到
具体的优化需要推公式,不好直观理解,变化也不大,直接讲怎么用。
如果满足四边形不等式,也就是
(经常会以
的形式出现)
(也可以是
满足四边形不等式和单调性
)
那么
随
单调递增。
记
为
取得最优解时候的
。
那么
或者
用哪个式子取决于题目。比如这道题用第二个好写
可以用一个平面
直观理解,就是左上低右下高这样
然后就可以优化枚举了。
照样是枚举
,
就是
,从上面那个范围里面枚举。
虽然是三层循环不过实际上就是
的
实际用起来不用搞什么证明四边形不等式还是证明单调性
写个
如果式子像像的,打个表看一下就好了
打表的时候要注意不要打那些冗余的状态,不然可能看不出来单调性
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
#define reg register int
int P,Q;
int Lst[105]={};
int Sum[105]={};
int F[105][105]={};
int S[105][105]={};
int main()
{
scanf("%d%d",&P,&Q);
for(reg i=1;i<=Q;++i)scanf("%d",&Lst[i]);
sort(Lst+1,Lst+1+Q); Lst[++Q]=P+1;
memset(F,0x3f,sizeof(F));
for(reg i=1;i<=Q;++i)Sum[i]=Sum[i-1]+Lst[i]-Lst[i-1]-1;
for(reg i=1;i<=Q;++i)S[i][i]=i,F[i][i]=0;
for(reg j=2;j<=Q;++j)for(reg i=j-1;i;--i)
for(reg t,k=S[i][j-1];k<=S[i+1][j];++k)
{
t=F[i][k]+F[k+1][j]+Sum[j]-Sum[i-1]+j-i-1;
if(t<=F[i][j])F[i][j]=t,S[i][j]=k;
}
printf("%d",F[1][Q]);
return 0;
}