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 dp[20][10][10][10][10];
void unit()
{//求和用sum[i][j]表示ij到左上角的和
    int total;
    for(int i=1; i<=8; i++)
        for(int j=1; j<=8; j++)
        {
            total=Mat[i][j];
            int x_1,y_1;
            x_1=i-1;
            y_1=j-1;
            if(x_1>0)
                total+=sum[x_1][j];
            if(y_1>0)
                total+=sum[i][y_1];
            if(x_1>0&&y_1>0)
                total-=sum[x_1][y_1];
            sum[i][j]=total;
        }
}

int account(int x_1,int y_1,int x_2,int y_2)
{//求(x_1,y_1)到(x_2,y_2)区间和
    int total=sum[x_2][y_2];
    int x_3,y_3;
    x_3=x_1-1;
    y_3=y_1-1;
    if(x_3>0)
        total-=sum[x_3][y_2];
    if(y_3>0)
        total-=sum[x_2][y_3];
    if(x_3>0&&y_3>0)
        total+=sum[x_3][y_3];
    return total*total;
}

int solve(int k,int x_1,int y_1,int x_2,int y_2)
{//记忆化dp
    if(dp[k][x_1][y_1][x_2][y_2]!=-1)
        return dp[k][x_1][y_1][x_2][y_2];
    if(k==1)
        return dp[k][x_1][y_1][x_2][y_2]=account(x_1,y_1,x_2,y_2);
    if(k>1)
    {
        int Min=Big;
        for(int i=y_1;i<y_2;i++)
        {//横向切割
            int first=account(x_1,y_1,x_2,i);
            int second=account(x_1,i+1,x_2,y_2);
            first+=solve(k-1,x_1,i+1,x_2,y_2);
            second+=solve(k-1,x_1,y_1,x_2,i);
            if(first>second)
                first=second;
            if(Min>first)
                Min=first;
        }
        for(int j=x_1;j<x_2;j++)
        {//纵向切割
            int first=account(x_1,y_1,j,y_2);
            int second=account(j+1,y_1,x_2,y_2);
            first+=solve(k-1,j+1,y_1,x_2,y_2);
            second+=solve(k-1,x_1,y_1,j,y_2);
            if(first>second)
                first=second;
            if(Min>first)
                Min=first;
        }
        return dp[k][x_1][y_1][x_2][y_2]=Min;
    }
    return dp[k][x_1][y_1][x_2][y_2]=Big;
}

int main()
{
    while(scanf("%d",&N)!=EOF)
    {
        double total=0.0;
        for(int i=1; i<=8; i++)
            for(int j=1; j<=8; j++)
            {
                 scanf("%d",&Mat[i][j]);
                 total+=Mat[i][j];
            }
        unit();
        memset(dp,-1,sizeof(dp));
         total=(total/N)*(total/N);
        double key=solve(N,1,1,8,8);
        key=key/N;
       key=sqrt(key-total);
       printf("%0.3f\n",key);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 12:26:15

poj 1191 棋盘分割 (压缩dp+记忆化搜索)的相关文章

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

vijos - P1456最小总代价 (状态压缩DP + 记忆化搜索)

P1456最小总代价 Accepted 标签:[显示标签] 描述 n个人在做传递物品的游戏,编号为1-n. 游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位:下一个人可以传递给未接过物品的任意一人. 即物品只能经过同一个人一次,而且每次传递过程都有一个代价:不同的人传给不同的人的代价值之间没有联系: 求当物品经过所有n个人后,整个过程的总代价是多少. 格式 输入格式 第一行为n,表示共有n个人(16>=n>=2): 以下为n*n的矩阵,第i+1行.第j列表示物

hdu1143 状态压缩dp 记忆化搜索写法

http://poj.org/problem?id=1143 Description Christine and Matt are playing an exciting game they just invented: the Number Game. The rules of this game are as follows. The players take turns choosing integers greater than 1. First, Christine chooses a

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。

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

POJ 1191 棋盘分割(DP)

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

poj 1088 滑雪(区间dp+记忆化搜索)

题目链接:http://poj.org/problem?id=1088 思路分析: 1>状态定义:状态dp[i][j]表示在位置map[i][j]可以滑雪的最长区域长度: 2>状态转移方程:由于由位置[i, j]只能向四个方向移动,所以子问题最多有四个:所以dp[i][j]为其邻域可以滑雪的最大区域长度加上从该位置滑到邻域的长度,即1: 代码如下: #include <cstdio> #include <iostream> #include <algorithm&

POJ 1088: 滑雪(经典 DP+记忆化搜索)

滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 74996   Accepted: 27818 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17

POJ 1191 棋盘分割

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