洛谷P1436 棋盤分割
阿新 • • 發佈:2019-02-17
sca can define esp 表示 string 矩形 == 過程
二維區間DP/記憶化搜索
原題是求均方差 需要用數學知識化簡 轉化為求最小平方和
狀態:f[k][x1][y1][x2][y2] 表示把左上端點為(x1,y1)、右下端點為(x2,y2)的棋盤分割成k個部分所得的最小平方和
邊界:當k=1時 為(x1,y1)到(x2,y2)的和的平方
目標:f[n][1][1][8][8]
狀態轉移方程復雜,DP需要四五層循環,這裏采用記憶化搜索
轉移過程:
for(int i=x1;i<=x2;++i){//枚舉行 把該矩形橫向切開 ans=min(ans,solve(k-1,x1,y1,i,y2)+solve(1,i+1,y1,x2,y2));//上半部分切成k-1塊 下半部分不動 ans=min(ans,solve(1,x1,y1,i,y2)+solve(k-1,i+1,y1,x2,y2));//上半部分不動 下半部分切成k-1塊 } for(int i=y1;i<=y2;++i){//枚舉列 把該矩形縱向切開 ans=min(ans,solve(k-1,x1,y1,x2,i)+solve(1,x1,i+1,x2,y2));//左半部分切成k-1塊 右半部分不動 ans=min(ans,solve(1,x1,y1,x2,i)+solve(k-1,x1,i+1,x2,y2));//左半部分不動 右半部分切成k-1塊 }
code:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define square(x) (x*x) #define s(x1,y1,x2,y2) (sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]) const int inf=0x3f3f3f3f; int ans,n,g[20][10][10][10][10],sum[20][20],a[20][20]; int solve(int k,int x1,int y1,int x2,int y2){ if(k==1) return g[k][x1][y1][x2][y2]=square(s(x1,y1,x2,y2)); if(g[k][x1][y1][x2][y2]!=-inf) return g[k][x1][y1][x2][y2]; int ans=inf; for(int i=x1;i<=x2;++i){ ans=min(ans,solve(k-1,x1,y1,i,y2)+solve(1,i+1,y1,x2,y2)); ans=min(ans,solve(1,x1,y1,i,y2)+solve(k-1,i+1,y1,x2,y2)); } for(int i=y1;i<=y2;++i){ ans=min(ans,solve(k-1,x1,y1,x2,i)+solve(1,x1,i+1,x2,y2)); ans=min(ans,solve(1,x1,y1,x2,i)+solve(k-1,x1,i+1,x2,y2)); } return g[k][x1][y1][x2][y2]=ans; } int main(){ scanf("%d",&n); for(int i=1;i<=8;++i) for(int j=1;j<=8;++j){ scanf("%d",&a[i][j]); sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j]; } for(int k=1;k<=15;++k) for(int x1=1;x1<=8;++x1) for(int x2=1;x2<=8;++x2) for(int x3=1;x3<=8;++x3) for(int x4=1;x4<=8;++x4) g[k][x1][x2][x3][x4]=-inf; ans=solve(n,1,1,8,8); printf("%d",ans); return 0; }
洛谷P1436 棋盤分割