HDOJ 1069 Monkey and Banana(LIS)
来源:互联网 发布:软件测试自学教程视频 编辑:程序博客网 时间:2024/05/05 21:48
题意,给出 n 种长方体的 a, b, c,每种都有无限多个,把它们盖成一个塔,要求相邻的下层长和宽都要严格大于上层。
刚开始想了个DAG上动态规划的做法(感觉直观上第一反应就是这种做法啊。。。)但是貌似有点小问题,虽然样例能过,但是会 STACK_OVERFLOW ,然后以为是记忆化搜索的问题,改成非递归的,直接 TLE 了。。。
于是上网找了正解。。。
显然每个长方体都有三种不同的形态,因为题目要求严格小于,所以每种长方体最多用三次。
把每种长方体的6种状态都枚举(长宽互换算两种,便于后面的排序),将其按先 x 后 y 排序(先 y 后 x 其实也一样。)
显然最优序列是排序后序列的一个子序列,而且是最长上升子序列。
此处上升的定义是 x 和 y 都要严格大于。
方程:dp[i] = h[i] + max(dp[j]) , j < i 且 i 可以放在 j 上。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 35 * 6;int n, vcnt;typedef struct Blk { int x, y, h;}Blk;Blk blk[maxn];int dp[maxn];void init(){ vcnt = 0; memset(dp, -1, sizeof(dp));}bool cmp(Blk a, Blk b){ if(a.x == b.x) return a.y > b.y; else return a.x > b.x;}void addv(int a, int b, int c){ blk[vcnt].x = a; blk[vcnt].y = b; blk[vcnt].h = c; vcnt++;}bool check(int i, int j){ return (blk[i].x > blk[j].x && blk[i].y > blk[j].y);}int main(){ int ca = 1; while(scanf("%d", &n) && n) { int a, b, c; init(); for(int i = 0; i < n; i++) { scanf("%d%d%d", &a, &b, &c); addv(a, b, c); addv(b, a, c); addv(a, c, b); addv(c, a, b); addv(b, c, a); addv(c, b, a); } sort(blk, blk + vcnt, cmp); for(int i = 0; i < vcnt; i++) { dp[i] = 0; for(int j = 0; j < i; j++) { if(check(j, i)) dp[i] = max(dp[j], dp[i]); } dp[i] += blk[i].h; } int ans = 0; for(int i = 0; i < vcnt; i++) ans = max(ans, dp[i]); printf("Case %d: maximum height = %d\n", ca++, ans); } return 0;}
顺便附一下 TLE 的 DAG 动态规划代码。。。。。。。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 110 * 3;int mat[maxn][maxn];int x[maxn], y[maxn], h[maxn];int outd[maxn];bool done[maxn];int n, vcnt;void init(){ memset(mat, -1, sizeof(mat)); memset(outd, 0, sizeof(outd)); memset(done, false, sizeof(done)); vcnt = 0;}void adde(int a, int b){ mat[a][b] = h[b]; outd[a]++;}void addv(int a, int b, int c){ x[vcnt] = a; y[vcnt] = b; h[vcnt] = c; for(int i = 0; i < vcnt; i++) { int s1 = x[i] - a, s2 = y[i] - b; int s3 = x[i] - b, s4 = y[i] - a; if(s1 * s2 > 0 || s3 * s4 > 0) { if(s1 > 0 || s3 > 0) adde(i, vcnt); else if(s1 < 0 || s3 < 0) adde(vcnt, i); } } vcnt++;}//int dpa[maxn];////int dp(int cur)//{// if(dpa[cur] != -1) return dpa[cur];// int ret = 0;// for(int i = first[cur]; i != -1; i = next[i])// ret = max(ret, wt[i] + dp(to[i]));// return dpa[cur] = ret;//}int dp[maxn];int main(){ int ca = 1; while(~scanf("%d", &n) && n) { init(); for(int i = 0; i < n; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); addv(a, b, c); addv(a, c, b); addv(b, c, a); } int ans = 0, cnt = 0;// memset(dpa, -1 ,sizeof(dpa)); while(cnt < vcnt) { for(int i = 0; i < vcnt; i++) { if(outd[i] == 0 && !done[i]) { dp[i] = 0; for(int j = 0; j < vcnt; j++) { if(mat[i][j] > 0) dp[i] = max(dp[i], mat[i][j] + dp[j]); } for(int j = 0; j < vcnt; j++) { if(mat[j][i] > 0) outd[j]--; } done[i] = 1; cnt++; } } } for(int i = 0; i < vcnt; i++) ans = max(ans, h[i] + dp[i]); printf("Case %d: maximum height = %d\n", ca++, ans); } return 0;}
STACK_OVERFLOW 的递归版本。。。。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 110 * 3, maxe = 130000;int x[maxn], y[maxn], h[maxn];int fr[maxe], to[maxe], wt[maxe];int first[maxn], next[maxe];int n, ecnt, vcnt;void init(){ memset(first, -1, sizeof(first)); memset(next, -1, sizeof(next)); ecnt = vcnt = 0;}void adde(int a, int b){ fr[ecnt] = a; to[ecnt] = b; wt[ecnt] = h[b]; next[ecnt] = first[a]; first[a] = ecnt; ecnt++;}void addv(int a, int b, int c){ x[vcnt] = a; y[vcnt] = b; h[vcnt] = c; for(int i = 0; i < vcnt; i++) { int s1 = x[i] - a, s2 = y[i] - b; int s3 = x[i] - b, s4 = y[i] - a; if(s1 * s2 > 0 || s3 * s4 > 0) { if(s1 > 0 || s3 > 0) adde(i, vcnt); else if(s1 < 0 || s3 < 0) adde(vcnt, i); } } vcnt++;}int dpa[maxn];int dp(int cur){ if(dpa[cur] != -1) return dpa[cur]; int ret = 0; for(int i = first[cur]; i != -1; i = next[i]) ret = max(ret, wt[i] + dp(to[i])); return dpa[cur] = ret;}int main(){ int ca = 1; while(~scanf("%d", &n) && n) { init(); for(int i = 0; i < n; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); addv(a, b, c); addv(a, c, b); addv(b, c, a); } int ans = 0; memset(dpa, -1 ,sizeof(dpa)); for(int i = 0; i < vcnt; i++) ans = max(ans, h[i] + dp(i)); printf("Case %d: maximum height = %d\n", ca, ans); } return 0;}
0 0
- HDOJ 1069 Monkey and Banana(LIS)
- HDOJ 1069 Monkey and Banana (结构体LIS)
- Monkey and Banana LIS
- HDOJ 1069 Monkey and Banana
- HDOJ 1069 Banana and Monkey
- HDOJ 1069 Monkey and Banana
- HDOJ-1069 Monkey and Banana
- hdoj 1069 Monkey and Banana
- HDOJ 1069 Monkey and Banana
- HDOJ-----1069Monkey and Banana
- HDU 1069 Monkey and Banana DP LIS
- HDU 1069 Monkey and Banana LIS变形
- 【DP|LIS】HDU-1069 Monkey and Banana
- hdu 1069 Monkey and Banana LIS变形
- Monkey and Banana Hdoj
- hdu/hdoj 1069 Monkey and Banana
- HDOJ 1069 Monkey and Banana 【DP】
- hdoj 1069 Monkey and Banana 【DP】
- NWBC登陆
- Android常用的注册监听方法
- ubuntu12.10-wubi-i386.tar.xz
- windows server 2008 服务器 重装IIS
- matlab 中的tic和toc
- HDOJ 1069 Monkey and Banana(LIS)
- mac系统如何显示和隐藏文件
- sky 数
- VS2008下面将 CString转化为char* 的问题
- ubuntu没有开启cron日志
- fix协议介绍6-重发消息
- Android的RelativeLayout的view的layout_marginBottom不起作用
- sqlplus 远程操作orcl
- 火狐FlashPlayerPlugin应用程序发送异常解决办法