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-10-16 06:27:54

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 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 4968 DP||记忆化搜索

给出N个人的平局分X 根据GPA规则计算可能的最高平均GPA和最低平均GPA 可以DP预处理出来所有结果  或者记忆化搜索 DP: #include "stdio.h" #include "string.h" int inf=100000000; double a[11][1100],b[11][1100]; double Max(double a,double b) { if (a<b) return b; else return a; } double M

poj 1651 dp 记忆化搜索

题意: 给出n个整数a1,a2,-,an,要求从中取出中间的n-2个数(两端的数不能取),取出每个数的代价为它两边的数和它的乘积,问取出这n-2个数的最小代价为多少? 限制: 3 <= n <= 100; 1 <= ai <= 100 思路: dp 记忆化搜索 对于每个过程其实就是,枚举最后取的数a[i],然后把区间[l,r]分割成[l,i]和[i,r]两部分. dp[l][r]=min(gao(l,i)+a[left]*a[i]*a[right]+gao(i,r))

POJ 2704 Pascal&#39;s Travels (基础记忆化搜索)

Pascal's Travels Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5328   Accepted: 2396 Description An n x n game board is populated with integers, one nonnegative integer per square. The goal is to travel along any legitimate path from t

UVa 10817 (状压DP + 记忆化搜索) Headmaster&#39;s Headache

题意: 一共有s(s ≤ 8)门课程,有m个在职教师,n个求职教师. 每个教师有各自的工资要求,还有他能教授的课程,可以是一门或者多门. 要求在职教师不能辞退,问如何录用应聘者,才能使得每门课只少有两个老师教而且使得总工资最少. 分析: 因为s很小,所以可以用状态压缩. dp(i, s1, s2)表示考虑了前i个人,有一个人教的课程的集合为s1,至少有两个人教的集合为s2. 在递归的过程中,还有个参数s0,表示还没有人教的科目的集合. 其中m0, m1, s0, s1, s2的计算用到位运算,还