ZOJ 1093 Monkey and Banana
2012-04-07 00:16
381 查看
和The Tower of Babylon一模一样,这里给出两个代码:一个是直接做的,不说了;
另一个是参考了Staginner大牛的方法,做了一个优化:将底面积按大到小排序,这样搜索时,只用从当前石块的下一个石块开始即可,最后打印 f[1] 即可,复杂度降低很明显的。
/* 方法二实际上有个错误,具体见后述。*/
方法一
为什么是按面积大小呢?因为会出现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。。
另一个是参考了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。。
相关文章推荐
- ZOJ 1093 Monkey and Banana
- 动态规划 zoj1093 Monkey and Banana
- ZOJ_1093_MonkeyAndBanana
- ZOJ 1093 Monkey and Banana
- ZOJ 1093 Monkey and Banana
- ZOJ 1093 Monkey and Banana
- ZOJ 1093 Monkey and Banana
- ZOJ_1093(Monkey and Banana)
- ZOJ 1093 Monkey and Banana(动态规划)
- ZOJ Problem Set - 1093 Monkey and Banana
- zoj1093 Monkey and Banana 动态规划
- zoj 1093 dp Monkey and Banana
- ZOJ 1093 Monkey and Banana (DP)
- zoj 1093 Monkey and Banana
- zoj-1093-Monkey and Banana
- ZOJ_1093_Monkey and Banana
- zoj1093题解 Monkey and Banana
- ZOJ 1093 Monkey and banana
- ZOJ 1093 Monkey and Banana(dp)
- HDU 1069 Monkey and Banana / ZOJ 1093 Monkey and Banana (最长路径)