# 4.5算法之动态规划 193:棋盘分割 区间dp

#### 题目

http://noi.openjudge.cn/ch0405/193/

#### 思路

https://blog.csdn.net/nnnnnnnnnnnny/article/details/51592665

#### 源码

``````//
//  193.cpp
//  test
//
//  Created by sgxm on 2020/8/3.
//

#include <stdio.h>
#include <iostream>
#include <math.h>
#include <memory.h>
#include <iomanip>
#include <string.h>
#define maxn 15
using namespace std;

int dp[15][8][8][8][8];
int s[8][8][8][8];
int tb[8][8];
int n;
int calSum(int x1,int y1,int x2,int y2){
int sum = 0;
for(int i = x1;i<=x2;++i){
for(int j = y1;j <= y2;++j){
sum+=tb[i][j];
}
}
return sum*sum;
}
int calDp(int k,int x1,int y1,int x2,int y2){
int MIN = 99999999;

if(dp[k][x1][y1][x2][y2]!=-1){
return dp[k][x1][y1][x2][y2];
}
if(k == 1){
return dp[k][x1][y1][x2][y2]=s[x1][y1][x2][y2];
}
dp[k][x1][y1][x2][y2]=MIN;
//横向划分
for(int x = x1;x<x2;++x){
int t1 = calDp(k-1, x1, y1, x, y2);
int t2 = calDp(k-1,x+1,y1,x2,y2);
int t = min(t1+s[x+1][y1][x2][y2],t2+s[x1][y1][x][y2]);
MIN = min(MIN,t);
}
for(int y = y1;y<y2;++y){
int t1 = calDp(k-1,x1,y1,x2,y);
int t2 = calDp(k-1,x1,y+1, x2, y2);
int t = min(t1+s[x1][y+1][x2][y2],t2+s[x1][y1][x2][y]);
MIN = min(MIN,t);
}
MIN=min(MIN,dp[k][x1][y1][x2][y2]);
//cout<<k<< " "<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<" = "<<MIN<<endl;
return  dp[k][x1][y1][x2][y2]=MIN;

}
int main(){
cin >> n;
for(int i = 0;i < 8;++i){
for(int j = 0;j < 8;++j){
cin >> tb[i][j];
}
}
memset(dp, -1,sizeof(dp));
//init Sum
for(int x1 = 0;x1 < 8;++x1){
for(int y1 = 0;y1 < 8;++y1){
for(int x2 = x1;x2<8;++x2){
for(int y2 = y1;y2<8;++y2){
s[x1][y1][x2][y2]=calSum(x1,y1,x2,y2);
}
}
}
}
//calDp(2,5,5,6,7);
int sum2 = calDp(n, 0, 0, 7, 7);
double res = 1.0*n*calDp(n, 0, 0, 7, 7)-s[0][0][7][7];
cout<<setiosflags(ios::fixed)<<setprecision(3)<<sqrt(res/(n*n))<<endl;
return 0;
}

``````