洛谷P1436
阿新 • • 發佈:2019-01-02
動態規劃:
我們設狀態$f[i][j][o][p][k]$表示一個矩形,左上角頂點座標為$(i,j)$,右下角頂點座標為$(o,p)$時分割了$k$次,也就是說現在是$k+1$塊
我們考慮狀態轉移:
列舉$ii$為切割某列,那麼狀態轉移如下:
$minn=min(minn,min(f[i][j][o][ii][k-1]+f[i][ii+1][o][p][0],f[i][j][o][ii][0]+f[i][ii+1][o][p][k-1]))$
列舉$ii$為切割某行,那麼狀態轉移如下:
$minn=min(minn,min(f[i][j][ii][p][k-1]+f[ii+1][j][o][p][0],f[i][j][ii][p][0]+f[ii+1][j][o][p][k-1]))$
初始化的時候弄個二維字首和就好了
程式碼:
#include<iostream> #include<cstdio> #define N 9 #define M 17 using namespace std; int n; int g[N][N],sum[N][N],f[N][N][N][N][M]; int main() { scanf("%d",&n); for(int i=1;i<=8;++i) for(int j=1;j<=8;++j) scanf("%d",&g[i][j]),sum[i][j]=sum[i-1][j]+sum[i][j-1]+g[i][j]-sum[i-1][j-1]; // for(int i=1;i<=8;++i) // { // for(int j=1;j<=8;++j) // printf("%d ",sum[i][j]); // printf("\n"); // } for(int i=1;i<=8;++i) for(int j=1;j<=8;++j) for(int o=i;o<=8;++o) for(int p=j;p<=8;++p) f[i][j][o][p][0]=sum[o][p]-sum[o][j-1]-sum[i-1][p]+sum[i-1][j-1],f[i][j][o][p][0]*=f[i][j][o][p][0]; for(int k=1;k<n;++k) for(int i=1;i<=8;++i) for(int j=1;j<=8;++j) for(int o=i;o<=8;++o) for(int p=j;p<=8;++p) { int minn=0x3f3f3f3f; for(int ii=j;ii<p;++ii) minn=min(minn,min(f[i][j][o][ii][k-1]+f[i][ii+1][o][p][0],f[i][j][o][ii][0]+f[i][ii+1][o][p][k-1])); for(int ii=i;ii<o;++ii) minn=min(minn,min(f[i][j][ii][p][k-1]+f[ii+1][j][o][p][0],f[i][j][ii][p][0]+f[ii+1][j][o][p][k-1])); f[i][j][o][p][k]=minn; } printf("%d",f[1][1][8][8][n-1]); return 0; }