题解 P4850 【[IOI2009]葡萄干raisins】
这才发现题解页面 $$ 多行书写,于是都改好,并在讨论区里测试过了,很惭愧,麻烦管理员再审核一遍,抱歉。
更好的阅读体验?不存在的!
既然大家都在用记忆化搜索,那我就来个 DP 题解吧。有了 O2 谁还会用 DP ?!
状态转移方程很容易推出来。设问题给出的矩阵为
这个很容易用记忆化搜索实现,但应如何 DP 呢?
容易想到,我们应该枚举每个行数和列数不都为
这个状态转移方程与上面的等价,但能方便我们用 DP 实现。
至于求子矩阵各元素之和,我们可以利用前缀和的思想,用
为了消去
核心代码如下:
// i,j,k,l 的意义已经说明
for(register int i,j,k=1,l,c,xs,ys,min,t;k<=n;++k)
for(l=1;l<=m;++l)
if(k!=1 || l!=1)
for(i=0,xs=n-k;i<=xs;++i)// xs 是为了限制 i,减少运算次数
for(j=0,ys=m-l;j<=ys;++j)//ys 同理
{
// min 表示将该子矩阵切开后的两个矩阵的最优解的最小值
min=0x7fffffff;
// 横着切
for(c=1;c<k;++c)
{
t=f[i][j][c][l]+f[i+c][j][k-c][l];
if(t<min)
min=t;
}
// 竖着切
for(c=1;c<l;++c)
{
t=f[i][j][k][c]+f[i][j+c][k][l-c];
if(t<min)
min=t;
}
// 状态转移方程
f[i][j][k][l]=min+sum[i+k][j+l]-sum[i+k][j]-sum[i][j+l]+sum[i][j];
}
不用开 O2 就可以过,评测记录证明一切。