算法题--棋盘分割

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

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <memory.h>
#include <cmath>
int s[9][9]={{0,0,0,0,0,0,0,0,0},{0,1,1,1,1,1,1,1,3},{0,1,1,1,1,1,1,1,1},{0,1,1,1,1,1,1,1,1},{0,1,1,1,1,1,1,1,1},
             {0,1,1,1,1,1,1,1,1},{0,1,1,1,1,1,1,1,1},{0,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,0,3}};   
using namespace std;
 //每个格子的分数
int sum[9][9];  //从(1,1)到(i,j)的矩形内分数之和
int res[15][9][9][9][9];    //记录fun分割后成n份后的最小平方和


int calSum(int x1, int y1, int x2, int y2){ //(x1,y1)到(x2,y2)的矩形的分数之和
    int h = sum[x2][y2] - sum[x2][y1-1] - sum[x1-1][y2] + sum[x1-1][y1-1];
    printf("from (%d, %d) to (%d, %d) : %d\n", x1,y1,x2,y2,h);
    return h;
}

int fun(int n, int x1, int y1, int x2, int y2){
    int t, a, b, c, e, MIN=10000000;
    if(res[n][x1][y1][x2][y2]!=-1)
        return res[n][x1][y1][x2][y2];
    if(n==1){   //递归退出条件,只剩一个矩形就不要分了
        t=calSum(x1,y1,x2,y2);
        res[n][x1][y1][x2][y2] = t*t;
        return t*t;
    }
    //下面继续分割
    //按照x轴(纵向)切一刀
    for(a=x1; a<x2; a++){
        c=calSum(a+1, y1, x2, y2);//取右边
        e=calSum(x1, y1, a, y2);//取左边
        t=min(fun(n-1, x1, y1, a, y2)+c*c, fun(n-1, a+1, y1, x2, y2)+e*e);
        if(MIN > t) MIN = t;
    }
    //按照y轴(横向)切一刀
    for(b=y1; b<y2; b++){
        c=calSum(x1, b+1, x2, y2);
        e=calSum(x1, y1, x2, b);
        t=min(fun(n-1, x1, y1, x2, b)+c*c, fun(n-1, x1, b+1, x2, y2)+e*e);
        if(MIN > t) MIN = t;
    }
    //更新res表值
    res[n][x1][y1][x2][y2] = MIN;
    cout<<"NO."<<n<<" MIN="<<MIN<<endl;
    return MIN;
}

int main(){
    memset(sum, 0, sizeof(sum));
    memset(res, -1, sizeof(res));
    int n;
    //cin>>n;
    n=3;

    for(int i=0;i<9;i++){
        for(int j=0;j<9;j++){
            cout<<s[i][j]<<" ";
        }
        cout<<endl;
    }

    //计算(1,1)到(i,j)的分数总和
    for(int i=1; i<9; i++){
        for(int j=1, rowsum=0; j<9; j++){
            //printf("cal...\n");
            //cin >> s[i][j];
            rowsum += s[i][j]; 
            //cout<<"rowsum="<<rowsum<<"  s["<<i<<"]["<<j<<"]="<<s[i][j]<<endl;
            sum[i][j] += sum[i-1][j]+rowsum;//每一行等于当前行加上上一行的值
            cout<<"sum["<<i<<"]["<<j<<"]="<<sum[i][j]<<endl;
        }
    }
    //标准差DX=sqrt((∑xi²-n(sum总/n)²/n)=sqrt(n∑xi²-sum总²/(n*n))
    double result = n*fun(n, 1, 1, 8, 8)-sum[8][8]*sum[8][8];
    cout<< result<<endl;
    cout << setiosflags(ios::fixed) << setprecision(3) << sqrt(result/(n*n)) << endl;
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值