首页 > 代码库 > 棋盘分割 动态规划

棋盘分割 动态规划


将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,

再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘。

(每次切割都只能沿着棋盘格子的边进行) 


原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。

现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。 
均方差,其中平均值,xi为第i块矩形棋盘的总分。 

请编程对给出的棋盘及n,求出O‘的最小值。 


#include <iostream>
#include <cstring>
#include <cmath>
#include <iomanip>
#include <fstream>
using namespace std;

const int MAX = 1 << 30;

int chessboard[9][9];
int sums[9][9][9][9];
double DP[20][9][9][9][9];

int N;

int main(){

    double totals = 0.0;
    double avg = 0.0;

    memset( chessboard, 0, sizeof( chessboard ) );
    memset( sums,       0, sizeof( sums ) );

    //fstream fin( "test.txt" );
    cin >> N;

    for( int i = 1; i <= 8; ++i ){
        for( int j = 1; j <= 8; ++j ){
            cin >> chessboard[i][j];
            sums[i][j][i][j] = chessboard[i][j];
            totals += chessboard[i][j];
            chessboard[i][j] += chessboard[i - 1][j] + chessboard[i][j - 1] - chessboard[i - 1][j - 1];
        }
    }

    avg = totals / ( N * 1.0 );

    for( int x1 = 1; x1 <= 8; ++x1 ){
        for( int y1 = 1; y1 <= 8; ++y1 ){
            for( int x2 = x1; x2 <= 8; ++x2 ){
                for( int y2 = y1; y2 <= 8; ++y2 ){
                    sums[x1][y1][x2][y2] = chessboard[x2][y2] - chessboard[x1 - 1][y2] -
                                           chessboard[x2][y1 - 1] + chessboard[x1 - 1][y1 - 1];
                    DP[0][x1][y1][x2][y2] = sums[x1][y1][x2][y2] * sums[x1][y1][x2][y2];
                }
            }
        }
    }

    for( int k = 1; k <= N - 1; ++k ){
        for( int x1 = 1; x1 <= 8; ++x1 ){
            for( int y1 = 1; y1 <= 8; ++y1 ){
                for( int x2 = x1; x2 <= 8; ++x2 ){
                    for( int y2 = y1; y2 <= 8; ++y2 ){

                        DP[k][x1][y1][x2][y2] = MAX;

                        for ( int mid = x1; mid < x2; ++mid ){
                            DP[k][x1][y1][x2][y2] = min( DP[k][x1][y1][x2][y2],
                                                         DP[0][x1][y1][mid][y2] + DP[k - 1][mid + 1][y1][x2][y2] );
                            DP[k][x1][y1][x2][y2] = min( DP[k][x1][y1][x2][y2],
                                                         DP[k - 1][x1][y1][mid][y2] + DP[0][mid + 1][y1][x2][y2] );
                        }

                        for( int mid = y1; mid < y2; ++mid ){
                            DP[k][x1][y1][x2][y2] = min( DP[k][x1][y1][x2][y2],
                                                         DP[0][x1][y1][x2][mid] + DP[k - 1][x1][mid + 1][x2][y2] );
                            DP[k][x1][y1][x2][y2] = min( DP[k][x1][y1][x2][y2],
                                                         DP[k - 1][x1][y1][x2][mid] + DP[0][x1][mid + 1][x2][y2] );
                        }
                    }
                }
            }
        }
    }

    double ans = DP[N - 1][1][1][8][8] / ( N * 1.0 ) - avg * avg;
    cout << setprecision(3) << fixed << sqrt(ans) << endl;

    return 0;
}


棋盘分割 动态规划