(中等) POJ 1191 棋盘分割,DP。

Description

将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行) 

原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。 
均方差,其中平均值,xi为第i块矩形棋盘的总分。 
请编程对给出的棋盘及n,求出O‘的最小值。

  题目好像很经典,DP问题,直接五维的DP,dp[i1][j1][i2][j2][k]表示从(i1,j1)到(i2,j2)切割k次的最小值。

代码如下:

// ━━━━━━神兽出没━━━━━━
//      ┏┓       ┏┓
//     ┏┛┻━━━━━━━┛┻┓
//     ┃           ┃
//     ┃     ━     ┃
//     ████━████   ┃
//     ┃           ┃
//     ┃    ┻      ┃
//     ┃           ┃
//     ┗━┓       ┏━┛
//       ┃       ┃
//       ┃       ┃
//       ┃       ┗━━━┓
//       ┃           ┣┓
//       ┃           ┏┛
//       ┗┓┓┏━━━━━┳┓┏┛
//        ┃┫┫     ┃┫┫
//        ┗┻┛     ┗┻┛
//
// ━━━━━━感觉萌萌哒━━━━━━

// Author        : WhyWhy
// Created Time  : 2015年07月18日 星期六 12时12分42秒
// File Name     : 1191.cpp

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>

using namespace std;

int map1[10][10];
int dp[10][10][10][10][20];

int sum(int i1,int j1,int i2,int j2)
{
    int ret=map1[i2][j2]-map1[i1-1][j2]-map1[i2][j1-1]+map1[i1-1][j1-1];

    ret*=ret;

    return ret;
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

    int N;
    int minn;

    scanf("%d",&N);

    for(int i=1;i<=8;++i)
        for(int j=1;j<=8;++j)
            scanf("%d",&map1[i][j]);

    for(int i=1;i<=8;++i)
        for(int j=1;j<=8;++j)
            map1[i][j]+=map1[i][j-1];

    for(int j=1;j<=8;++j)
        for(int i=1;i<=8;++i)
            map1[i][j]+=map1[i-1][j];

    for(int i1=1;i1<=8;++i1)
        for(int j1=1;j1<=8;++j1)
            for(int i2=i1;i2<=8;++i2)
                for(int j2=j1;j2<=8;++j2)
                    dp[i1][j1][i2][j2][0]=sum(i1,j1,i2,j2);

    for(int k=1;k<N;++k)
        for(int i1=1;i1<=8;++i1)
            for(int j1=1;j1<=8;++j1)
                for(int i2=i1;i2<=8;++i2)
                    for(int j2=j1;j2<=8;++j2)
                    {
                        minn=0x3f3f3f3f;

                        for(int q=i1;q<i2;++q)
                            minn=min(minn,min(dp[i1][j1][q][j2][k-1]+sum(q+1,j1,i2,j2),dp[q+1][j1][i2][j2][k-1]+sum(i1,j1,q,j2)));

                        for(int q=j1;q<j2;++q)
                            minn=min(minn,min(dp[i1][j1][i2][q][k-1]+sum(i1,q+1,i2,j2),dp[i1][q+1][i2][j2][k-1]+sum(i1,j1,i2,q)));

                        dp[i1][j1][i2][j2][k]=minn;
                    }

    long double ans=(long double)(dp[1][1][8][8][N-1]);

    printf("%.3f\n",sqrt(ans/N-(long double)map1[8][8]*map1[8][8]*1.0/((long double)(N)*N)));

    return 0;
}

时间: 2024-10-08 15:42:29

(中等) POJ 1191 棋盘分割,DP。的相关文章

POJ 1191 棋盘分割

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

poj - 1191 - 棋盘分割(dp)

题意:将一个8*8的棋盘(每个单元正方形有个分值)沿直线(竖或横)割掉一块,留下一块,对留下的这块继续这样操作,总共进行n - 1次,得到n块(1 < n < 15)矩形,每个矩形的分值就是单元正方形的分值的和,问这n个矩形的最小均方差. 题目链接:http://poj.org/problem?id=1191 -->>此题中,均方差比较,等价于方差比较,等价于平方和比较.. 状态:dp[x1][y1][x2][y2][i]表示将(x1, y1)到(x2, y2)的矩形分割i次的最小

POJ 1191 棋盘分割(DP)

题目链接 题意 : 中文题不详述. 思路 : 黑书上116页讲的很详细.不过你需要在之前预处理一下面积,那样的话之后列式子比较方便一些. 先把均方差那个公式变形, 另X表示x的平均值,两边平方得 平均值是一定的,所以只要让每个矩形的总分的平方和尽量小即可.左上角坐标为(x1,y1)右下角坐标为(x2,y2)的棋盘,设总和为s[][][][],切割k次以后得到k+1块矩形的总分平方和是d[k][][][][],则可以沿着横线切也可以沿着竖线切,然后选一块接着切,递归下去,状态转移方程 d[k,x1

POJ 1191 棋盘分割(区间DP)题解

题意:中文题面 思路:不知道直接暴力枚举所有情况行不行... 我们可以把答案转化为 所以答案就是求xi2的最小值,那么我们可以直接用区间DP来写.设dp[x1][y1][x2][y2][k]为x1 y1 到 x2 y2 区间分割为k份的最下平方和,显然k = 1是就是区间和的平方. 写了6层for,写出来自己都不信... 交C++才过... 代码: #include<cmath> #include<stack> #include<cstdio> #include<

poj 1191 棋盘分割 (压缩dp+记忆化搜索)

一,题意: 中文题 二,分析: 主要利用压缩dp与记忆化搜索思想 三,代码: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> using namespace std; const int Big=20000000; int Mat[10][10]; int N; int sum[10][10]; int

POJ百炼——1191棋盘分割

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

poj 1191 棋盘切割 (压缩dp+记忆化搜索)

一,题意: 中文题 二.分析: 主要利用压缩dp与记忆化搜索思想 三,代码: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> using namespace std; const int Big=20000000; int Mat[10][10]; int N; int sum[10][10]; int

#RANK_3 1191:棋盘分割

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

(中等) POJ 3034 Whac-a-Mole,DP。

Description While visiting a traveling fun fair you suddenly have an urge to break the high score in the Whac-a-Mole game. The goal of the Whac-a-Mole game is to… well… whack moles. With a hammer. To make the job easier you have first consulted the f