P1436 棋盘分割



分析
考虑多维的dp
dp[a][b][c][d][k]
将矩形[a,b][c,d]表示划分k次得到的最大值
明显答案即为dp[1][1][8][8][k]
初始状态为dp[i][j][ii][jj][1]=矩阵和的平方
转移方程:
枚举i<=x dp[i][j][ii][jj][k]=min(dp[i][j][x][jj][1]+dp[x+1][j][ii][jj][k-1],dp[i][j][x][jj][k-1]+dp[x+1][j][ii][jj][1])
就是把矩阵横着分为两半
同理枚举y

点击查看代码
#include
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x7fffffff
ll dp[10][10][10][10][20];
ll a[10][10];
int n;
void init(){
	for(int i=1;i<=8;i++)
	for(int j=1;j<=8;j++)
	a[i][j]+=a[i][j-1];
	for(int j=1;j<=8;j++)
	for(int i=1;i<=8;i++)
	a[i][j]+=a[i-1][j];
}
ll find(int x1,int y1,int x2,int y2){
  return a[x2][y2]-a[x1-1][y2]-a[x2][y1-1]+a[x1-1][y1-1];  	
}
ll p(ll a){
	return a*a;
}
void dd(){
	for(int i=1;i<=8;i++)
	for(int j=1;j<=8;j++)
	for(int x=i;x<=8;x++)
	for(int y=j;y<=8;y++)
	dp[i][j][x][y][1]=p(find(i,j,x,y));
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=8;i++)
	for(int j=1;j<=8;j++)
	scanf("%d",&a[i][j]);
	init();dd();
	for(int k=2;k<=n;k++)
	for(int x1=1;x1<=8;x1++)
	for(int y1=1;y1<=8;y1++)
	for(int x2=x1;x2<=8;x2++)
	for(int y2=y1;y2<=8;y2++){
		dp[x1][y1][x2][y2][k]=1<<30;
		for(int i=x1;i