1 10 20 30 2 6 8 10 5 5 5 7 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 5 31 41 59 26 53 58 97 93 23 84 62 64 33 83 27 0
Case 1: maximum height = 40 Case 2: maximum height = 21 Case 3: maximum height = 28 Case 4: maximum height = 342 题意: 有一群闲得无聊的科学家打算测试猴子的IQ,科学家想出了一个方法来测试猴子们. 首先科学家把猴子最喜欢吃的香蕉放在屋顶,在给它们n个种类的石块, 然后看看猴子们能不能利用这些石块拿到香蕉. 石块是一个矩形立方体,可以任意摆放,一个石块可以放在另一个石块的前提是石块的宽和长要严格大于另一个石块 的宽和长. 猴子现在叠石块,结果问猴子所能叠出的石块的最大高度为多少. 题解: 典型的DAG上的动态规划问题,一个石块可以叠在另一个石块时,就连一条有向边,然后就记忆化搜索从i个石块开始搜索的最大高度. AC代码:#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <map> #include <vector> #include <cmath> #include <cctype> using namespace std; typedef long long ll; typedef pair<int,int>P; const int M = 200; int to,G[M][M],d[M]; struct Node { int x,y,z; bool operator < (const Node &a) const { return a.x > x || (a.x == x && a.y > y); } } p[M]; void make(int a,int b,int c) //石块可以有六种摆放方法; { p[to].x = a; p[to].y = b; p[to++].z = c; p[to].x = b; p[to].y = a; p[to++].z = c; p[to].x = a; p[to].y = c; p[to++].z = b; p[to].x = c; p[to].y = a; p[to++].z = b; p[to].x = b; p[to].y = c; p[to++].z = a; p[to].x = c; p[to].y = b; p[to++].z = a; } int dp(int i) //记忆化搜索; { int& ans = d[i]; if(ans) return ans; ans = p[i].z; for(int j = 0; j < to; j++) if(G[i][j]) ans = max(ans,dp(j) + p[i].z); return d[i] = ans; } void debug() //调试用的; { for(int i = 0; i < to; i++) printf("%d %d %d\n",p[i].x,p[i].y,p[i].z); } int main() { int n,Max,cnt = 0; while(~scanf("%d",&n) && n) { to = Max = 0; memset(G,0,sizeof(G)); memset(d,0,sizeof(d)); while(n--) { int a,b,c; scanf("%d %d %d",&a,&b,&c); if(a == b && b == c) { p[to].x = a; p[to].y = b; p[to++].z = c; continue; } make(a,b,c); } //debug(); for(int i = 0; i < to; i++) for(int j = 0; j < to; j++) if(i != j) if(p[i].x < p[j].x && p[i].y < p[j].y) G[i][j] = 1; //建图 for(int i = 0; i < to; i++) Max = max(Max,dp(i)); printf("Case %d: maximum height = %d\n",++cnt,Max); } return 0; }
Monkey and Banana(DAG上的动态规划问题)
原文地址:http://blog.csdn.net/zsgg_acm/article/details/43019341