菜板 动态规划

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

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

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

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

如今须要把棋盘按上述规则切割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。

均方差

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcGFuZG9yYV9tYWRhcmE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >,当中平均值

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcGFuZG9yYV9tYWRhcmE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >。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-08-11 10:25:21

菜板 动态规划的相关文章

Leetcode 494 Target Sum 动态规划 背包+滚动数据

这是一道水题,作为没有货的水货楼主如是说. 题意:已知一个数组nums {a1,a2,a3,.....,an}(其中0<ai <=1000(1<=k<=n, n<=20))和一个数S c1a1c2a2c3a3......cnan = S, 其中ci(1<=i<=n)可以在加号和减号之中任选. 求有多少种{c1,c2,c3,...,cn}的排列能使上述等式成立. 例如: 输入:nums is [1, 1, 1, 1, 1], S is 3. 输出 : 5符合要求5种

活动选择的贪心算法与动态规划(未完成)

// greedy_algorithm.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include<queue> using namespace std; #define NofActivity 11 int c[NofActivity + 1][NofActivity + 1]; int reme[NofActivity + 1][NofActivity + 1]; //活动的

求不相邻金币相加和的最大值--动态规划1

求不相邻金币相加和的最大值. 输入n个金币的金币面值(正数自定义),求这些金币不相邻和的最大值. 动态规划问题1 设f(n)为第n个金币数的最大值,f(0)=0,f(1)=a[1],输入的数组从下标为1开始. f(n)=max{a[n]+f(n-2),f(n-1)}. 代码如下: import java.util.Scanner; public class Jin_bi_zui_da_zhi { public static void main(String[] args) { Scanner s

[动态规划] 黑客的攻击 Hacker&#39;s CrackDown Uva 11825

抽象为数学模型就是,  取尽可能多的互不相交的子集 ,  使得每一个子集都能覆盖全集 #include <algorithm> #include <cstring> #include <cstdio> using namespace std; int n; int P[1000],cover[1000],f[1000]; int main(){ scanf("%d", &n); for (int i = 0; i < n;i++) {

Beauty Of algorithms(七)动态规划 钢条分割 矩阵链乘 最长公共子序列 最优二叉树

1.动态规划                动态规划的方法与方法类似,英文"dynamic programming",这里的programming不是程序的意思,而是一种表格法.都是通过组合子问题的解来解决原问题,分治方法将划分为互不相交的子问题,递归的求解子问题,再将它们的解组合起来求出原问题的解.与之相反动态规划应用于子问题的重叠情况,即不同的子问题具有公共的子问题,子问题的求解是递归进行 的,将其划分为更小的子问题,动态规划,每个子问题只求解一次,将其保存在表格中,从而无需每次求

Hdoj 1176 免费馅饼 【动态规划】

免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 26110    Accepted Submission(s): 8905 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的1

Fibonacci斐波拉契数列----------动态规划DP

n==10 20 30 40 50 46 体验一下,感受一下,运行时间 #include <stdio.h>int fib(int n){ if (n<=1)     return 1; else            return fib(n-1)+fib(n-2); }int main( ){ int n; scanf("%d",&n); printf("%d\n" ,fib(n) );} 先 n==10 20 30 40 50 46

pat 1068 动态规划/Fina More Conis

1068. Find More Coins (30) Eva loves to collect coins from all over the universe, including some other planets like Mars. One day she visited a universal shopping mall which could accept all kinds of coins as payments. However, there was a special re

动态规划(4)——最长上升子序列(作业题NYOJ201)

作业题 描述 小白同学这学期有一门课程叫做<数值计算方法>,这是一门有效使用数字计算机求数学问题近似解的方法与过程,以及由相关理论构成的学科-- 今天他们的Teacher S,给他们出了一道作业题.Teacher S给了他们很多的点,让他们利用拉格朗日插值公式,计算出某严格单调函数的曲线.现在小白抄下了这些点,但是问题出现了,由于我们的小白同学上课时走了一下神,他多抄下来很多点,也就是说这些点整体连线不一定还是严格递增或递减的了.这可怎么处理呢.为此我们的小白同学制定了以下的取点规则: 1.取