题目
有n(n≤30)种立方体,每种都有无穷多个。要求选一些立方体摞成一根尽量高的柱子 (可以自行选择哪一条边作为高),使得每个立方体的底面长宽分别严格小于它下方立方体的底面长宽。
思路
DAG的不确定起点终点的最长路
1.状态及指标函数:d(i),在编号为i的立方体做塔的最底部,所能叠出的最高高度。(包括此立方体)
2.状态转移方程:
3.对于DAG的不确定起点终点的最长短路,没有递推做法,只能记忆化搜索,不需要设递归边界。算是比较简单的一种。
思路
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;
const int maxn = 1000+100;
struct edge{
int a, b, h;
}P[maxn];
int n, x, G[maxn][maxn], d[maxn];
// DAG不确定起点终点的最长短路不需要递归边界
int dp(int i){
int &ans = d[i];
if (ans != -1) return ans;
ans = P[i].h;
_rep(j,1,x)
if(G[j][i])
ans = max(ans, dp(j) + P[i].h);
return ans;
}
int main(){
int kase = 0;
while(scanf("%d",&n) == 1 && n){
x=1; int a, b, c;
_for(i,0,n){
scanf("%d%d%d",&a,&b,&c);
P[x].a = a, P[x].b = b, P[x++].h = c;
P[x].a = a, P[x].h = b, P[x++].b = c;
P[x].h = a, P[x].b = b, P[x++].a = c;
}
x--;
memset(G, 0, sizeof(G));
_rep(i,1,x)
_rep(j,1,x)
if(i!=j)
if ((P[i].a < P[j].a && P[i].b < P[j].b) || (P[i].a < P[j].b && P[i].b < P[j].a) )
G[i][j] = 1;
memset(d,-1,sizeof(d));
int maxans = 0;
_rep(i,1,x)
maxans = max(maxans, dp(i));
printf("Case %d: maximum height = %d\n",++kase,maxans);
}
return 0;
}
废话
1.DP只要想清楚思路,AC起题来好快啊