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<ii
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<bits/stdc++.h>
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<x2;i++)
dp[x1][y1][x2][y2][k]=min(dp[x1][y1][x2][y2][k],min(dp[x1][y1][i][y2][k-1]+dp[i+1][y1][x2][y2][1],dp[x1][y1][i][y2][1]+dp[i+1][y1][x2][y2][k-1]));
for(int j=y1;j<y2;j++)
dp[x1][y1][x2][y2][k]=min(dp[x1][y1][x2][y2][k],min(dp[x1][y1][x2][j][k-1]+dp[x1][j+1][x2][y2][1],dp[x1][y1][x2][j][1]+dp[x1][j+1][x2][y2][k-1]));
}
cout<<dp[1][1][8][8][n]<<endl;
return 0;
}

浙公网安备 33010602011771号