1. 程式人生 > >動態規劃--P1436 棋盤分割

動態規劃--P1436 棋盤分割

傳送門 dpdp,把切割變成往外擴充套件,f[i][x1][y1][x2][y2]f[i][x1][y1][x2][y2]表示第ii次擴充套件到(x1,y1)(x2,y2)(x1,y1) (x2,y2)的矩形最小的平方和,然後列舉上一次從哪兒擴充套件過來就好了

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
#define inf 0x3f3f3f3f
using namespace std;
int m,a[20][20],sum[20][20]; LL f[20][10][10][10][10]; const int n=8; inline int rd(){ int x=0,f=1;char c=' '; while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar(); while(c<='9' && c>='0') x=x*10+c-'0',c=getchar(); return x*f; } inline void init(){ m=rd(); for(int i=1;i<=n;i++) for(int
j=1;j<=n;j++) a[i][j]=rd(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) sum[i][j]=sum[i][j-1]+a[i][j]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) sum[i][j]+=sum[i-1][j]; } inline int min(int x,int y){return x<y?x:y;} inline LL calc(int x1,int y1,int x2,int y2){ int
val=sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]; return 1LL*val*val; } int main(){ init(); for(int x1=1;x1<=n;x1++) for(int y1=1;y1<=n;y1++) for(int x2=x1;x2<=n;x2++) for(int y2=y1;y2<=n;y2++) f[1][x1][y1][x2][y2]=calc(x1,y1,x2,y2); for(int i=2;i<=m;i++) for(int x1=1;x1<=n;x1++) for(int y1=1;y1<=n;y1++) for(int x2=x1;x2<=n;x2++) for(int y2=y1;y2<=n;y2++){ int tmp=inf; for(int j=x1;j<x2;j++) tmp=min(tmp,f[i-1][x1][y1][j][y2]+calc(j+1,y1,x2,y2)), tmp=min(tmp,f[i-1][j+1][y1][x2][y2]+calc(x1,y1,j,y2)); for(int j=y1;j<y2;j++) tmp=min(tmp,f[i-1][x1][y1][x2][j]+calc(x1,j+1,x2,y2)), tmp=min(tmp,f[i-1][x1][j+1][x2][y2]+calc(x1,y1,x2,j)); f[i][x1][y1][x2][y2]=tmp; } printf("%lld\n",f[m][1][1][n][n]); return 0; }