BZOJ3810: [Coci2015]Stanovi

显然某个矩形要分开必存在贯穿它的分割线,然后直接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\n",s);
}
posted @ 2017-04-03 04:04  f321dd  阅读(326)  评论(1编辑  收藏  举报