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

题目链接http://poj.org/problem?id=1191

Problem: 1191User: yinjianMemory: 568KTime: 16MSLanguage: C++Result: Accepted

解题报告:

1、公式可以利用数学方法化简,就是求各个矩阵上的数(的和)的平方和最小。

2、每一次分割都有四种情况(递归)。

3、每一次分割的位置要进行比较,从而找到最佳。

#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h>

using namespace std;

int s[9][9];//每个格子的分数
int sum[9][9];//(1,1)到(i,j)的矩形分数的和
int res[15][9][9][9][9];//fun的记录表

int calsum(int x1,int y1,int x2,int y2)//(x1,y1)到(x2,y2)的矩形分数和
{
    return sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];
}

int fun(int n,int x1,int y1,int x2,int y2)//以(x1,y1)为左上角,(x2,y2)为右下角的矩形的棋盘分割成n分后的最小平方和
{
    int t,a,b,c,e;
    int MIN=0x3f3f3f3f;
    if(res[n][x1][y1][x2][y2]!=-1)
        return res[n][x1][y1][x2][y2];
    if(n==1)
    {
        t=calsum(x1,y1,x2,y2);
        res[n][x1][y1][x2][y2]=t*t;
        return t*t;
    }
    for(a=x1;a<x2;a++)
    {
        c=calsum(a+1,y1,x2,y2);//右边的矩阵的和
        e=calsum(x1,y1,a,y2);//左边的矩阵的和
        t=min(fun(n-1,x1,y1,a,y2)+c*c,fun(n-1,a+1,y1,x2,y2)+e*e);
        if(MIN>t) MIN=t;
    }
    for(b=y1;b<y2;b++)
    {
        c=calsum(x1,b+1,x2,y2);//下面的矩阵的和
        e=calsum(x1,y1,x2,b);//上面的矩阵的和
        t=min(fun(n-1,x1,y1,x2,b)+c*c,fun(n-1,x1,b+1,x2,y2)+e*e);
        if(MIN>t) MIN=t;
    }
    res[n][x1][y1][x2][y2]=MIN;
    return MIN;
}

int main()
{
    memset(sum,0,sizeof(sum));
    memset(res,-1,sizeof(res));
    int n;
    scanf("%d",&n);
    for(int i=1;i<9;i++)
    {
        for(int j=1,rowsum=0;j<9;j++)
        {
            scanf("%d",&s[i][j]);
            rowsum=rowsum+s[i][j];
            sum[i][j]=sum[i-1][j]+rowsum;
        }
    }
    double result=n*fun(n,1,1,8,8)-sum[8][8]*sum[8][8];
    printf("%.3f\n",sqrt(result/(n*n)));
    return 0;
}
时间: 2024-10-13 22:02:22

递归,记忆化搜索,(棋盘分割)的相关文章

棋盘分割(记忆化搜索)

棋盘分割 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块矩形棋盘.

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

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

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

[BZOJ 1048] [HAOI2007] 分割矩阵 【记忆化搜索】

题目链接:BZOJ - 1048 题目分析 感觉这种分割矩阵之类的题目很多都是这样子的. 方差中用到的平均数是可以直接算出来的,然后记忆化搜索 Solve(x, xx, y, yy, k) 表示横坐标范围 [x, xx], 纵坐标范围 [y, yy] 的矩阵切成 k 块的最小 sigma((Vi - Ave)^2) . 然后再递归将矩阵分得更小,直到 k 为 1 的时候直接返回相应的值. 代码 #include <iostream> #include <cstdlib> #incl

搜索分析(DFS、BFS、递归、记忆化搜索)

搜索分析(DFS.BFS.递归.记忆化搜索) 1.线性查找 在数组a[]={0,1,2,3,4,5,6,7,8,9,10}中查找1这个元素. (1)普通搜索方法,一个循环从0到10搜索,这里略. (2)递归(从中间向两边) 1 //递归一定要写成记忆化递归 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool vis[11]; 5 int count1=0; 6 7 void search(int n){ 8 count1++; 9

BZOJ-1048: [HAOI2007]分割矩阵 (记忆化搜索)

1048: [HAOI2007]分割矩阵 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1040  Solved: 751[Submit][Status][Discuss] Description 将一个a*b的数字矩阵进行如下分割:将原矩阵沿某一条直线分割成两个矩阵,再将生成的两个矩阵继续如此分割(当然也可以只分割其中的一个),这样分割了(n-1)次后,原矩阵被分割成了n个矩阵.(每次分割都只能沿着数字间的缝隙进行)原矩阵中每一位置上有一个分值

数字三角形——递归、递推、记忆化搜索

数字三角形 描述: 有一个由非负整数组成的三角形,第一行只有一个数,除了最下行之外没个数的左下方和右下方各有一个数. 问题: 从第一行的数开始,每次可以往左下或右下走一格,直到走到最下行,把沿途经过的数全部加起来.如何走才能使得这个和尽量大? 分析: 不难看出此题是一个动态的决策问题:每次有两种选择--左下或右下.如果用回溯法求出所有的可能的路线,就可以从中选出最优的路线.但和往常一样,回溯法的效率太低:一个n层数字三角形的完整路线有2^n条,当n很大时回溯法的速度将让人无法忍受.因此本题讨论用

动态规划 数字三角形(递归,递推,记忆化搜索)

题目要求: 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 在上面的数字三角形中寻找在上面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大.路径上的每一步都只能往左下或右下走.只需要求出这个最大和即可,不必给出具体路径. 三角形的行数大于1小于等于100,数字为 0 - 99 输入格式: 5 //三角形行数.下面是三角形 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 解题思路: 用二维数组存放数字三角形 D[r][j] //表示第i行第j个元素的

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

动态规划&mdash;&mdash;数字三角形(递归or递推or记忆化搜索)

动态规划的核心就是状态和状态转移方程. 对于该题,需要用抽象的方法思考,把当前的位置(i,j)看成一个状态,然后定义状态的指标函数d(i,j)为从格子出发时能得到的最大和(包括格子本身的值). 在这个状态定义下,原问题的解就是d(i,j). 下面看一下不同状态之间如何转移.从格子(i,j)出发有两种策略.如果向左走,则到(i+1,j)后需要求"从(i+1,j)出发能得到的最大和"这一问题,即d(i+1,j). 类似的,往右走之后需要求解d(i+1,j+1).由于可以在这两个决策中自由选