前言
决策单调性得好好学。
理解不深,瞎掰扯。
题目
讲解
经典题。
这道题的决策单调性可以由四边形不等式证明,形如 \(w(a,c)+w(b,d)\le w(a,d)+w(b,c) (a\le b<c\le d).\)
决策单调性可以用分治快速求解,我们考虑分 \(k'\) 块,显然其只和 \(k'-1\) 有关,所以我们一层一层解决问题。
具体的,我们每次二分一个中点,求出它的最优决策点,然后左右两个区间分别递归下去,顺便改一下决策区间,根据决策单调性即可满足复杂度。
时间复杂度 \(O(nk\log_n)\)。
代码
原谅我的工地英语
//12252024832524
#include <bits/stdc++.h>
#define TT template<typename T>
using namespace std;
typedef long long LL;
const int MAXN = 4005;
const int INF = 0x3f3f3f3f;
int n,m;
int pre[MAXN][MAXN],dp[MAXN][MAXN];
LL Read()
{
LL x = 0,f = 1; char c = getchar();
while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
return x * f;
}
TT void Put1(T x)
{
if(x > 9) Put1(x/10);
putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
if(x < 0) putchar('-'),x = -x;
Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}
int now;
int Sum(int l,int r){return (pre[r][r]-pre[l-1][r]-pre[r][l-1]+pre[l-1][l-1]) >> 1;}
void solve(int l,int r,int ql,int qr)//section to be solved,operation section
{
if(l > r) return;
int mid = (l+r) >> 1,ID = ql,MIN = INF;
for(int i = ql,val;i <= qr && i <= mid;++ i)
if((val = Sum(i,mid)+dp[i-1][now-1]) < MIN)
{
MIN = val;
ID = i;
}
dp[mid][now] = MIN;
solve(l,mid-1,ql,ID);
solve(mid+1,r,ID,qr);
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n = Read(); m = Read();
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= n;++ j)
pre[i][j] = pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+Read();
memset(dp,INF,sizeof(dp));
dp[0][0] = 0;
for(now = 1;now <= m;++ now) solve(1,n,1,n);
Put(dp[n][m],'\n');
return 0;
}