显然某个矩形要分开必存在贯穿它的分割线,然后直接dp,f[i][j][k]表示i行j列,顶边界的状态为k的最小代价,直接转移。顶边界本来有16种状态,然而去掉对称只剩8种,其中全顶的只有1个,顶3边的只有2(n+m)个,有nm个的只有3种。
比较懒就写的7nm的状态。
#include<cstdio> typedef long long ll; void upd1(ll&a,ll b){a>b?a=b:0;} ll sqr(ll s){return s*s;} const int N=301; ll f[N][N][7]; int main(){ int n,m,z; scanf("%d%d%d",&n,&m,&z); ll s=sqr(n*m-z); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j){ for(int k=0;k<7;++k) f[i][j][k]=sqr(i*j-z); for(int k=1;k<i;++k){ upd1(f[i][j][0],f[k][j][0]+f[i-k][j][0]); upd1(f[i][j][2],f[k][j][2]+f[i-k][j][0]); upd1(f[i][j][3],f[k][j][3]+f[i-k][j][3]); upd1(f[i][j][4],f[k][j][1]+f[i-k][j][1]); upd1(f[i][j][5],f[k][j][2]+f[i-k][j][2]); upd1(f[i][j][6],f[k][j][6]+f[i-k][j][3]); } for(int k=1;k<j;++k){ upd1(f[i][j][1],f[i][k][1]+f[i][j-k][1]); upd1(f[i][j][2],f[i][k][2]+f[i][j-k][1]); upd1(f[i][j][3],f[i][k][0]+f[i][j-k][0]); upd1(f[i][j][4],f[i][k][4]+f[i][j-k][4]); upd1(f[i][j][5],f[i][k][5]+f[i][j-k][4]); upd1(f[i][j][6],f[i][k][2]+f[i][j-k][2]); } } for(int i=1;i<n;++i) upd1(s,f[i][m][6]+f[n-i][m][6]); for(int j=1;j<m;++j) upd1(s,f[n][j][5]+f[n][m-j][5]); printf("%lld ",s); }