Luogu P1436 棋盘分割 暴力DP

我的天,,,,,n=8,k<=15,,,这怕不是暴力DP+高维数组。。。。


开一个五维数组f[k][i][j][p][q]表示从(i,j)到(p,q)中分成k个矩形最小的平方和。

然后初始化时用上二维前缀和

DP时有些像区间DP,枚举分割线,分成两部分,取min就好

#include<cstdio>
#include<iostream>
#include<cstring>
#define R register int
#define For(i,a,b) for(R i=a;i<=b;++i)
#define ffor(i,a,b) for(R i=b;i>=a;--i)
const int N=8;
using namespace std;
inline int g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
}
inline void ckmn(int& a,int b) {b<a?a=b:a=a;}
int n;
int f[N<<1][N][N][N][N],a[N][N],s[N][N];
signed main() { memset(f,0x3f,sizeof(f)); n=g();
    For(i,1,8) For(j,1,8) a[i][j]=g();
    For(i,1,8) For(j,1,8) s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
    For(i,1,8) For(j,1,8) For(p,i,8) For(q,j,8) {
        R tmp=s[p][q]-s[p][j-1]-s[i-1][q]+s[i-1][j-1]; f[1][i][j][p][q]=tmp*tmp;
    } For(tk,2,n) ffor(i,1,8) ffor(j,1,8) For(p,i,8) For(q,i,8) {
        For(t,i+1,p) ckmn(f[tk][i][j][p][q],min(f[tk-1][i][j][t-1][q]+f[1][t][j][p][q],f[1][i][j][t-1][q]+f[tk-1][t][j][p][q]));
        For(t,j+1,q) ckmn(f[tk][i][j][p][q],min(f[tk-1][i][j][p][t-1]+f[1][i][t][p][q],f[1][i][j][p][t-1]+f[tk-1][i][t][p][q]));
    } printf("%d\n",f[n][1][1][8][8]);
}

第一次define for循环,太多了。。QAQ。。。


2019.04.28

猜你喜欢

转载自www.cnblogs.com/Jackpei/p/10785833.html