棋盘分割 动态规划

将一个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;
}
时间: 2024-10-15 07:57:01

棋盘分割 动态规划的相关文章

POJ百炼——1191棋盘分割

1191:棋盘分割 总时间限制: 1000ms 内存限制: 65536kB 描述 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次切割都只能沿着棋盘格子的边进行)原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和.现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小.均方差,其中平均值,xi为第i块矩形棋盘的总分.请编程对给出的棋盘及

POJ1191——棋盘分割

棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12456   Accepted: 4389 Description 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次切割都只能沿着棋盘格子的边进行) 原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和.现在需要把棋盘按上述规

POJ 1191 棋盘分割

棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11938   Accepted: 4207 Description 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次切割都只能沿着棋盘格子的边进行) 原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和.现在需要把棋盘按上述规

递归,记忆化搜索,(棋盘分割)

题目链接http://poj.org/problem?id=1191 Problem: 1191User: yinjianMemory: 568KTime: 16MSLanguage: C++Result: Accepted 解题报告: 1.公式可以利用数学方法化简,就是求各个矩阵上的数(的和)的平方和最小. 2.每一次分割都有四种情况(递归). 3.每一次分割的位置要进行比较,从而找到最佳. #include <stdio.h> #include <math.h> #includ

【POJ 1191】 棋盘分割(DP)

[POJ 1191] 棋盘分割(DP) Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13811   Accepted: 4917 Description 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次切割都只能沿着棋盘格子的边进行) 原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分

棋盘分割(记忆化搜索)

棋盘分割 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 501    Accepted Submission(s): 248 Problem Description 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.

NOI 193棋盘分割.cpp

193:棋盘分割 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次切割都只能沿着棋盘格子的边进行)原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和.现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小.均方差,其中平均值,xi为第i块矩形棋盘的

POJ1991 NOI1999棋盘分割

棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 15581   Accepted: 5534 Description 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次切割都只能沿着棋盘格子的边进行) 原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和.现在需要把棋盘按上述规

poj1191 棋盘分割【区间DP】【记忆化搜索】

棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16263   Accepted: 5812 Description 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次切割都只能沿着棋盘格子的边进行) 原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和.现在需要把棋盘按上述规