您的位置:首页 > 其它

ZOJ 1093 Monkey and Banana

2012-04-07 00:16 381 查看
和The Tower of Babylon一模一样,这里给出两个代码:一个是直接做的,不说了;

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

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

方法一

# include <stdio.h>
# include <memory.h>
# include <stdlib.h>

typedef struct {
int x, y, h;
}block;

int n;
int f[92];
block a[92];

int cmp(const void *x, const void *y)
{
return (*(int *)x<*(int *)y ? -1:1);
}

int dp(int i);            /* 记忆化搜索,f[i] = dp(i); f[i]定义为从第i个箱子出发所能到达的最大高度 */

int main()
{
int tmp[3], i, maxH, cnt;

cnt = 0;
while (~scanf("%d", &n))
{
if (!n) break;

++cnt;
n *= 3;
for ( i = 1; i <= n; ++i)
{
scanf("%d%d%d", &tmp[0], &tmp[1], &tmp[2]);
qsort(tmp, 3, sizeof(int), cmp);
a[i].x = tmp[0]; a[i].y = tmp[1]; a[i].h = tmp[2];  ++i;
a[i].x = tmp[1]; a[i].y = tmp[2]; a[i].h = tmp[0];  ++i;
a[i].x = tmp[0]; a[i].y = tmp[2]; a[i].h = tmp[1];
}

memset(f, 0, sizeof(f));

maxH = 0;
for (i = 1; i <= n; ++i)
if (maxH < dp(i)) maxH = f[i];

printf("Case %d: maximum height = %d\n", cnt, maxH);
}

return 0;
}

int dp(int i)
{
int k, tmp;

if (f[i]) return f[i];
f[i] = a[i].h;
for ( k = 1; k <= n; ++k)
if (a[k].x < a[i].x && a[k].y < a[i].y && f[i] < (tmp = dp(k)+a[i].h))
f[i] = tmp;

return f[i];
}


# include <stdio.h>
# include <memory.h>
# include <stdlib.h>

typedef struct {
int x, y, h;
}block;

int n;
int f[92];
block a[92];

int cmp(const void *xx, const void *yy)
{
return (*(int *)xx<*(int *)yy ? -1:1);
}

int block_cmp(const void *xx, const void *yy)
{
return (*(block *)xx).x * (*(block *)xx).y > (*(block *)yy).x * (*(block *)yy).y ? -1:1;
}

int dp(int i);            /* 记忆化搜索,f[i] = dp(i); f[i]定义为从第i个箱子出发所能到达的最大高度 */

int main()
{
int tmp[3], i, cnt;

cnt = 0;
while (~scanf("%d", &n))
{
if (!n) break;

++cnt;
n *= 3;
for ( i = 1; i <= n; ++i)
{
scanf("%d%d%d", &tmp[0], &tmp[1], &tmp[2]);
qsort(tmp, 3, sizeof(int), cmp);
a[i].x = tmp[0]; a[i].y = tmp[1]; a[i].h = tmp[2];  ++i;
a[i].x = tmp[1]; a[i].y = tmp[2]; a[i].h = tmp[0];  ++i;
a[i].x = tmp[0]; a[i].y = tmp[2]; a[i].h = tmp[1];
}

memset(f, 0, sizeof(f));
qsort(a+1, n, sizeof(block), block_cmp);

printf("Case %d: maximum height = %d\n", cnt, dp(1));
}

return 0;
}

int dp(int i)
{
int k, tmp;

if (f[i]) return f[i];
f[i] = a[i].h;
for ( k = i+1; k <= n; ++k)
if (a[k].x < a[i].x && a[k].y < a[i].y && f[i] < (tmp = dp(k)+a[i].h))
f[i] = tmp;

return f[i];
}


为什么是按面积大小呢?因为会出现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。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: