HDU1069 Monkey and Banana(动态规划)
Monkey and Banana
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1069
题目大意:
研究人员有$n$种类型的砖块,每种类型的砖块都有无限个。第i块砖块的长宽高分别用$xi,yi,zi$来表示。 同时,由于砖块是可以旋转的,每个砖块的3条边可以组成6种不同的长宽高。
在构建塔时,当且仅当A砖块的长和宽都分别小于B砖块的长和宽时,A砖块才能放到B砖块的上面,因为必须留有一些空间让猴子来踩。
你的任务是编写一个程序,计算猴子们最高可以堆出的砖块们的高度。
解题思路:
使用将砖的类型扩大到三倍,也就是说一块转三个不同大小的面都作为一次底。因为数据范围较小,可以记录哪个砖可以放在哪那块砖上面,然后dfs求解最大值,需要记忆化数组剪枝。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define debug(a) cout<<#a<<":"<<a<<endl; 4 typedef long long ll; 5 const int N=1e6+7; 6 const ll mod=1e9+7; 7 int maxn,minn; 8 struct aa{ 9 int a,b,w; 10 }node; 11 12 vector<aa>arr; 13 vector<aa>mp[N]; 14 int dp[N]; 15 16 int dfs(int a){ 17 if(dp[a]){ 18 return dp[a]; 19 } 20 for(int i=0;i<mp[a].size();i++){ 21 dp[a]=max(dfs(mp[a][i].a)+mp[a][i].w,dp[a]); //第a块砖做底能垒到的高度的最大值 22 } 23 return dp[a]; 24 } 25 26 27 int main(){ 28 int n,num=0; 29 int a,b,c; 30 while(cin>>n&&n){ 31 num++; 32 arr.clear(); 33 memset(dp,0,sizeof(dp)); 34 maxn=0; 35 arr.push_back(node); 36 for(int i=1;i<=n;i++){ 37 scanf("%d%d%d",&a,&b,&c); 38 node.a=a; node.b=b; node.w=c; //一块砖的三种放法全部记录 39 arr.push_back(node); 40 node.a=c; node.w=a; 41 arr.push_back(node); 42 node.b=a; node.w=b; 43 arr.push_back(node); 44 } 45 for(int i=1;i<=3*n;i++){ //判断砖与砖之间的关系 46 mp[i].clear(); 47 for(int j=1;j<=3*n;j++){ 48 if(arr[i].a>arr[j].a&&arr[i].b>arr[j].b){ 49 node.a=j; 50 node.w=arr[j].w; 51 mp[i].push_back(node); 52 } 53 else if(arr[i].b>arr[j].a&&arr[i].a>arr[j].b){ 54 node.a=j; 55 node.w=arr[j].w; 56 mp[i].push_back(node); 57 } 58 } 59 } 60 for(int i=1;i<=3*n;i++){ //每一块砖都做一次底 61 maxn=max(maxn,arr[i].w+dfs(i)); 62 } 63 printf("Case %d: maximum height = %d\n",num,maxn); 64 } 65 66 67 68 return 0; 69 }