棋盘问题,递归。

将一个8*8的棋盘进行如下分割: 
将原棋盘割下一块矩形棋盘并使剩下部分也是矩形, 
再将剩下的部分继续如此分割, 这样割了(n-1)次后, 
连同最后剩下的矩形棋盘共有n块矩形棋盘. 
 (每次切割都只能沿着棋盘格子的边进行) 
 
允许的分割方案 2 
 不允许的分割方案 原棋盘上每一格有一个分值, 
 一块矩形棋盘的总分为其所含各格分值之和
现在需要把棋盘按上述规则分割成 n 块矩形棋盘, 
 并使各矩形棋盘总分的均方差最小 
 
均方差 , 其中平均值 , 
 xi 为第 i 块矩形棋盘的总分 
请编程对给出的棋盘及 n, 求出 σ 的最小值 
 第1行为一个整数n (1 < n < 15)
第2行至第9行每行为8个小于100的非负整数, 表示棋盘上
相应格子的分值 
 每行相邻两数之间用一个空格分隔 
 
输出 
 仅一个数, 为σ (四舍五入精确到小数点后三位) 
4 样例输入 

1 1 1 1 1 1 1 3 
1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 0 
1 1 1 1 1 1 0 3 
样例输出 

//

这个题和以前做过的挑战程序设计里面的分棒子差不多,都是递归的解决问题,不算很难。

/

#include<iostream>

#include<iomanip>
using namespace std;
const int maxNum = 9;
double getResult(int n,int x1,int y1,int x2,int y2);
int tmpresult[15][maxNum][maxNum][maxNum][maxNum];
int board[maxNum][maxNum];
int gradeSum[maxNum][maxNum];
int calSum(int x1,int y1,int x2,int y2);
int main(){
memset(tmpresult,-1,sizeof(tmpresult));
memset(gradeSum,0,sizeof(gradeSum));
int n;
cin>>n;
for(int i = 1;i <= 8;i++)
{
int lineSum(0);
for(int j = 1;j <= 8;j++)
{
cin>>board[i][j];
lineSum += board[i][j];
gradeSum[i][j] = gradeSum[i - 1][j] + lineSum;//gradeSum数组用来储存每个格子的分数
}
}
double result = n*getResult(n,1,1,8,8)-gradeSum[8][8]*gradeSum[8][8]; 
 cout<<setiosflags(ios::fixed)<<setprecision(3)<<sqrt(result/(n*n))<<endl; 
 return 0; 

int calSum(int x1,int y1,int x2,int y2){
return gradeSum[x2][y2]-gradeSum[x1 - 1][y2]-gradeSum[x2][y1 - 1]+gradeSum[x1][y1];
}
double getResult(int n,int x1,int y1,int x2,int y2){
int minNum(10000);
int t,s1,s2,line,vertical;
if(tmpresult[n][x1][y1][x2][y2] != -1)
return tmpresult[n][x1][y1][x2][y2];
if(n == 1)
{
t = calSum(x1,y1,x2,y2);
tmpresult[n][x1][y1][x2][y2] = t * t;
return t * t;
}
for(vertical = x1;vertical < x2;line++)
{
s1 = calSum(x1,y1,vertical,y2);
s2 = calSum(vertical+1,y1,x2,y2);
t = min((getResult(n-1,x1,y1,vertical,y2)+s2 * s2),(getResult(n-1,vertical+1,y1,x2,y2)+s1 * s1));
if(t < minNum)
minNum = t;
}
for(line = y1;line < y2;line++)
{
s1 = calSum(x1,y1,x2,line);
s2 = calSum(x1,line + 1,x2,y2);
t = min((getResult(n - 1,x1,y1,x2,line)+s2 * s2),(getResult(n - 1,x1,line + 1,x2,y2)+s1 * s1));
if(t < minNum)
minNum = t;
}
tmpresult[n][x1][y1][x2][y2] = minNum;
return minNum;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值