zoukankan      html  css  js  c++  java
  • UVA1629Cake slicing(记忆化搜索)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51190

    紫书P305

    题意分析:一个矩形蛋糕上有好多个樱桃,现在要做的就是切割最少的距离,切出矩形形状的小蛋糕,让每个蛋糕上都有一个樱桃,问最少切割距离是?

    解题思路:既然是切割蛋糕,可以感受到是一个无限切割的过程(递归?)反正有这种感觉存在。然后数据是20*20。那么就试试记忆化搜索。我们设dp[u][d][l][r]为u(up)为上届d(down)为下界,l为左界,r为右界的最小切割距离。边界就是当整块区域只有一个樱桃显然不用切割了,返回0。当整块区域没有樱桃时,这块区域就是无效的切割,设置为无穷。

    弱逼没点想法,看了大神的题解顿时恍然大悟

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<cmath>
     6 #include<algorithm>
     7 using namespace std;
     8 const int INF = 0x3f3f3f3f;
     9 int n, m, dp[25][25][25][25];
    10 bool has[25][25]; //记录格点是否有樱桃
    11 
    12 int sum(int u, int d, int l, int r) //统计区域内的樱桃数
    13 {
    14     int total = 0;
    15     for(int i = u + 1; i <= d; i++)
    16     {
    17         for(int j = l + 1; j <= r; j++)
    18         {
    19             if(has[i][j])
    20                 total++;
    21             if(total == 2)  //只要至少两个就得分割
    22                 return 2;
    23         }
    24     }
    25     return total;
    26 }
    27 
    28 
    29 int dfs(int u, int d, int l, int r)
    30 {
    31     int &res = dp[u][d][l][r];
    32     if(res != -1)
    33         return res;
    34     int total = sum(u, d, l, r);
    35     if(total == 1)
    36         return res = 0;
    37     if(total == 0)
    38         return res = INF;
    39     res = INF;  // 找res的最小,要先把他设成最大值
    40     for(int i = u + 1; i < d; i++) 
    41         res = min(res, dfs(u, i, l, r) + dfs(i, d, l, r) + (r - l)); //按行分割
    42     for(int i = l + 1; i < r; i++)
    43         res = min(res, dfs(u, d, l, i) + dfs(u, d, i, r) + d - u); //按列分割
    44     return res;
    45 }
    46 int main()
    47 {
    48     int test = 0,k;
    49     while(scanf("%d%d%d", &n, &m, &k) != EOF)
    50     {
    51         int x,y;
    52         memset(has, 0, sizeof(has));
    53         memset(dp, -1, sizeof(dp));
    54         for(int i = 0; i < k; i++)
    55         {
    56             scanf("%d%d", &x, &y);
    57             has[x][y] = 1;
    58         }
    59         printf("Case %d: %d
    ", ++test,dfs(0, n, 0, m)); //上开下闭的区间
    60     }
    61     return 0;
    62 }
    View Code

     

  • 相关阅读:
    Matlab矢量图图例函数quiverkey
    FVCOM泥沙模块河流边界处理
    高分辨率格式
    linux字节
    转:海洋地震采集
    海上地震勘探视频
    如何设置默认打印机
    如何查询是否正式刊物
    屏幕截图
    Word中文字与公式不对齐
  • 原文地址:https://www.cnblogs.com/zhaopAC/p/5216061.html
Copyright © 2011-2022 走看看