题意:有n种立方体 每种都有无穷多个 要求选一些立方体叠成一根尽量高的柱子 (可以自行选择哪条边为高 )使得每个立方体的底面都严格小于他下方的立方体
为DAG模型
在任何时候 只有顶面的尺寸会影响到后续决策!!!!
可以采用a,b来表示顶面尺寸 不过落实到dp会有一个问题: 因为a,b的值可能会很大 所以用(idx,k)来表示 idx为立方体的编号 k为第几条边作为高
dp[i][j]表示以 第i个立方体 第k条边为高(注意有序化) 作为最底下的立方体的最大高度
所以可以很轻松得出dp主过程:
fo(i,n) fo(j,3) ans=max(ans,dp(i,j));
就是枚举完所有的
状态总数为 n 每个状态的决策有n个 所以 时间复杂度n2
#include<bits/stdc++.h> using namespace std; #define N 40 #define fo(i,n) for(int i=0;i<(n);i++) int n; int block[N][N]; int d[N][N]; void getdimensions(int *v,int i,int j) { int idx=0; fo(a,3) if(a!=j)v[idx++]=block[i][a]; } int dp(int i,int j) { int& ans=d[i][j];//为了不用打d[i][j] 更加快 if(ans>0)return ans;//避免重复计算 ans=0; int v[2],v2[2]; getdimensions(v,i,j);//读取该状态下 顶面的边长 fo(a,n) fo(b,3) { getdimensions(v2,a,b); if(v[0]>v2[0]&&v[1]>v2[1])ans=max(ans,dp(a,b)); } ans+=block[i][j];//改变了d[i][j] return ans;//又传递了值 } int main() { int cas=0; while(~scanf("%d",&n)&&n) { fo(i,n) { fo(j,3)scanf("%d",&block[i][j]); sort(block[i],block[i]+3);//注意一定要有序化 才能比较 } memset(d,0,sizeof d); int ans=0; fo(i,n)//这里反过来也是一样的 因为是一个记忆化枚举的过程 所有的状态都会被枚举到 fo(j,3) ans=max(ans,dp(i,j)); printf("Case %d: maximum height = %d\n",++cas,ans); } return 0; }