• ZOJ 1093 Monkey and Banana


    和The Tower of Babylon一模一样,这里给出两个代码:一个是直接做的,不说了;

    另一个是参考了Staginner大牛的方法,做了一个优化:将底面积按大到小排序,这样搜索时,只用从当前石块的下一个石块开始即可,最后打印 f[1] 即可,复杂度降低很明显的。

    /* 方法二实际上有个错误,具体见后述。*/

    方法一
     1 # include <stdio.h>
    2 # include <memory.h>
    3 # include <stdlib.h>
    4
    5 typedef struct {
    6 int x, y, h;
    7 }block;
    8
    9 int n;
    10 int f[92];
    11 block a[92];
    12
    13 int cmp(const void *x, const void *y)
    14 {
    15 return (*(int *)x<*(int *)y ? -1:1);
    16 }
    17
    18 int dp(int i); /* 记忆化搜索,f[i] = dp(i); f[i]定义为从第i个箱子出发所能到达的最大高度 */
    19
    20 int main()
    21 {
    22 int tmp[3], i, maxH, cnt;
    23
    24 cnt = 0;
    25 while (~scanf("%d", &n))
    26 {
    27 if (!n) break;
    28
    29 ++cnt;
    30 n *= 3;
    31 for ( i = 1; i <= n; ++i)
    32 {
    33 scanf("%d%d%d", &tmp[0], &tmp[1], &tmp[2]);
    34 qsort(tmp, 3, sizeof(int), cmp);
    35 a[i].x = tmp[0]; a[i].y = tmp[1]; a[i].h = tmp[2]; ++i;
    36 a[i].x = tmp[1]; a[i].y = tmp[2]; a[i].h = tmp[0]; ++i;
    37 a[i].x = tmp[0]; a[i].y = tmp[2]; a[i].h = tmp[1];
    38 }
    39
    40 memset(f, 0, sizeof(f));
    41
    42 maxH = 0;
    43 for (i = 1; i <= n; ++i)
    44 if (maxH < dp(i)) maxH = f[i];
    45
    46 printf("Case %d: maximum height = %d\n", cnt, maxH);
    47 }
    48
    49 return 0;
    50 }
    51
    52 int dp(int i)
    53 {
    54 int k, tmp;
    55
    56 if (f[i]) return f[i];
    57 f[i] = a[i].h;
    58 for ( k = 1; k <= n; ++k)
    59 if (a[k].x < a[i].x && a[k].y < a[i].y && f[i] < (tmp = dp(k)+a[i].h))
    60 f[i] = tmp;
    61
    62 return f[i];
    63 }
     1 # include <stdio.h>
    2 # include <memory.h>
    3 # include <stdlib.h>
    4
    5 typedef struct {
    6 int x, y, h;
    7 }block;
    8
    9 int n;
    10 int f[92];
    11 block a[92];
    12
    13 int cmp(const void *xx, const void *yy)
    14 {
    15 return (*(int *)xx<*(int *)yy ? -1:1);
    16 }
    17
    18 int block_cmp(const void *xx, const void *yy)
    19 {
    20 return (*(block *)xx).x * (*(block *)xx).y > (*(block *)yy).x * (*(block *)yy).y ? -1:1;
    21 }
    22
    23 int dp(int i); /* 记忆化搜索,f[i] = dp(i); f[i]定义为从第i个箱子出发所能到达的最大高度 */
    24
    25 int main()
    26 {
    27 int tmp[3], i, cnt;
    28
    29 cnt = 0;
    30 while (~scanf("%d", &n))
    31 {
    32 if (!n) break;
    33
    34 ++cnt;
    35 n *= 3;
    36 for ( i = 1; i <= n; ++i)
    37 {
    38 scanf("%d%d%d", &tmp[0], &tmp[1], &tmp[2]);
    39 qsort(tmp, 3, sizeof(int), cmp);
    40 a[i].x = tmp[0]; a[i].y = tmp[1]; a[i].h = tmp[2]; ++i;
    41 a[i].x = tmp[1]; a[i].y = tmp[2]; a[i].h = tmp[0]; ++i;
    42 a[i].x = tmp[0]; a[i].y = tmp[2]; a[i].h = tmp[1];
    43 }
    44
    45 memset(f, 0, sizeof(f));
    46 qsort(a+1, n, sizeof(block), block_cmp);
    47
    48 printf("Case %d: maximum height = %d\n", cnt, dp(1));
    49 }
    50
    51 return 0;
    52 }
    53
    54 int dp(int i)
    55 {
    56 int k, tmp;
    57
    58 if (f[i]) return f[i];
    59 f[i] = a[i].h;
    60 for ( k = i+1; k <= n; ++k)
    61 if (a[k].x < a[i].x && a[k].y < a[i].y && f[i] < (tmp = dp(k)+a[i].h))
    62 f[i] = tmp;
    63
    64 return f[i];
    65 }

    为什么是按面积大小呢?因为会出现a[i].x>b[j].x && a[i].y<a[j].y的情况,如果按照能否放上去的方式排序,这种情况将处于无序状态;

    ZOJ这道题的测试数据看来是弱的,因为实际上即使做了上述的优化,最终还必须循环查找f[i]的最大值,可以举个例子:第一个是一个6*6的正方形,第二个是3*11的长方形,后面的都可以放在这个长方形上(或者给三组数据,第三组为2*10),那么最终f[2]显然是最大的,所以方法二对应的代码48行那里还必须循环查找最大值,但是判的结果是AC, 0MS。。

  • 相关阅读:
    linux系统中fdisk命令进行磁盘分区
    linux系统中挂载mount命令、umount命令
    linux系统中du命令
    linux系统中独立冗余磁盘阵列RAID
    linux vmware虚拟机添加硬盘
    linux系统中部署raid10磁盘阵列
    linux系统中配置磁盘容量配额服务(quota)
    linux系统中添加swap交换分区、删除swap交换分区
    linux系统中软链接和硬链接
    调试流程(暂定)
  • 原文地址:https://www.cnblogs.com/JMDWQ/p/2435534.html
Copyright © 2020-2023  润新知