uva437-The Tower of Babylon

题目链接请戳 这里

 

解题思路

带权DAG上的最大权和路。

可以先对每个木块的三个维度排序方便后续处理。

(思路来自紫书)

dp[i][j]表示以第i个木块为底,j=0/1/2时以长/宽/高 为高,时能组成的最高高度。

 

代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 40
using namespace std;

int blo[N][3];
int dp[N][3];
int n;

int d(int x, int y)
{
  int &ans = dp[x][y];
  int u, v;
  if (ans > 0) return ans;
  //y决定谁为高
  if (y == 0) { ans = blo[x][0]; u = blo[x][1]; v = blo[x][2]; }
  else if (y == 1) { ans = blo[x][1]; u = blo[x][0]; v = blo[x][2]; }
  else { ans = blo[x][2]; u = blo[x][0]; v = blo[x][1]; }
  //因为事先对维度排序,可以减少判断
  for (int j = 1; j <= n; j++)
    for (int k = 0; k <= 2; k++) {
      if (k == 0 && blo[j][1] < u && blo[j][2] <v)
    ans = max(ans, d(j, k) + blo[x][y]);
      else if (k == 1 && blo[j][0] <u && blo[j][2] <v)
    ans = max(ans, d(j, k) + blo[x][y]);
      else if (k == 2 && blo[j][0] <u && blo[j][1] <v)
    ans = max(ans, d(j, k) + blo[x][y]);
    }
  return ans;
}

int main()
{
  int t = 0;
  while (scanf("%d", &n) != EOF && n) {
    memset(dp, 0, sizeof(dp));
    //现对三个维度排序
    for (int i = 1; i <= n; i++) {
      scanf("%d%d%d", &blo[i][0], &blo[i][1], &blo[i][2]);
      sort(blo[i], blo[i] + 3);
    }
    for (int i = 1; i <= n; i++)
      for (int k = 0; k <= 2; k++) dp[i][k] = d(i, k);
    int maxn = 0;
    for (int i = 1; i <= n; i++)
      for (int k = 0; k <= 2; k++) 
    maxn = max(maxn, dp[i][k]);
    printf("Case %d: maximum height = ", ++t);
    printf("%d\n", maxn);
  }
  return 0;
}

 

posted @ 2016-12-23 23:45  啊嘞  阅读(228)  评论(0编辑  收藏  举报