有用点个赞呗@_@
题目描述
To celebrate the victory of the war, Pisces has decided to build a splendid palace. The craftsmen has brought back n kinds of cube materials from the dwarf kingdom. The length, width, and height of each material are a, b and c respectively. To make the palace magnificent, the craftsmen have to stack these materials together. Material i can be stacked on material j if and only if
a
i
<
a
j
⋂
b
i
<
b
j
a_i<a_j⋂b_i<b_j
ai<aj⋂bi<bj, or
a
i
<
b
j
⋂
b
i
<
a
j
a_i<b_j⋂b_i<a_j
ai<bj⋂bi<aj. Pisces wants to know how high these materials can stack at most
题意简述:
有n个长方体,a,b,c是长,宽,高,
若
a
i
<
a
j
⋂
b
i
<
b
j
a_i<a_j⋂b_i<b_j
ai<aj⋂bi<bj, 或
a
i
<
b
j
⋂
b
i
<
a
j
a_i<b_j⋂b_i<a_j
ai<bj⋂bi<aj,则说明i可以放在j上
求可以达到的最大高度。
样例输入
The first line contains an integer T (1≤T≤10)(1≤T≤10), which denotes the number of test cases.
For each of the test cases, the first line contains an integer n(1≤n≤2∗103)(1≤n≤2∗103), which represents the number of materials. Each of the next n lines contains 3 integers a, b and c (1≤a,b,c≤1000)(1≤a,b,c≤1000), which represents the size of a material.
1
3
2 3 5
4 3 4
3 3 3
样例输出
For each test case, print the maximum height.
9
算法简述
暴力建图,用拓扑排序的方法以一个拓扑序列的次序对每个节点dp即可
细节
如何建图?
若i可以放在j上,那么加一条i到j的有向边,这里我用的是链式前向*存法
如何dp?
dp[i]代表以i为最上面的方块为i能达到的最高高度
对于正在处理的节点:
枚举其出度边,边终点为j,则更新dp[j]
dp[j]=max(dp[j],dp[i]+j.c);
代码
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stdio.h>
#include <string.h>
using namespace std;
#pragma warning(disable:4996)
#define MAX(a,b) (a>b?a:b)
#define MIN(a,b) (a<b?a:b)
const int maxn = 2005, maxm = 1999005;
int H[maxn], NXT[maxm],E[maxm], eSize;
void add(int from ,int to)
{
eSize++;
E[eSize] = to;
NXT[eSize] = H[from];
H[from] = eSize;
}
int n, T;
struct dat
{
int a, b, c;
};
dat v[maxn];
int tag[maxn];
int dp[maxn];
int indegree[maxn];
int main()
{
scanf("%d", &T);
while (T--)
{
memset(dp, 0, sizeof(dp));
memset(H, 0, sizeof(H));
memset(NXT, 0, sizeof(NXT));
memset(indegree, 0, sizeof(indegree));
eSize = 0;
scanf("%d", &n);
for (int i = 1 ;i <= n; i++)
{
scanf("%d%d%d", &v[i].a, &v[i].b, &v[i].c);
}
for (int i = 1; i <= n; i++)
{
for (int j = i + 1; j <= n; j++)
{
if (MAX(v[i].a,v[i].b) > MAX(v[j].a,v[j].b) && MIN(v[i].a,v[i].b) > MIN(v[j].a, v[j].b))
{
add(i, j);
indegree[j]++;
}
if (MAX(v[i].a, v[i].b) < MAX(v[j].a, v[j].b) && MIN(v[i].a, v[i].b) < MIN(v[j].a, v[j].b))
{
add(j, i);
indegree[i]++;
}
}
}
queue<int> Q;
for (int i = 1; i <= n; i++)
{
if (!indegree[i])
{
Q.push(i);
}
}
while (!Q.empty())
{
int x = Q.front(); Q.pop();
dp[x] = MAX(dp[x], v[x].c);
for (int i = H[x]; i; i = NXT[i])
{
indegree[E[i]]--;
dp[E[i]] = MAX(dp[E[i]], dp[x] + v[E[i]].c);
if (!indegree[E[i]])
{
Q.push(E[i]);
}
}
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
ans = MAX(ans, dp[i]);
}
printf("%d\n", ans);
}
}
扩展
任意面可以做底的情况
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stdio.h>
#include <string.h>
using namespace std;
#pragma warning(disable:4996)
#define MAX(a,b) (a>b?a:b)
#define MIN(a,b) (a<b?a:b)
const int maxn = 2005, maxm = 1999005;
struct edg
{
int to, flg1, flg2;
};
edg E[maxm];
int H[maxn], NXT[maxm], eSize;
void add(int from ,int to,int flg1,int flg2)
{
eSize++;
E[eSize] = { to,flg1,flg2 };
NXT[eSize] = H[from];
H[from] = eSize;
}
int n, T;
struct dat
{
int a, b, c;
};
dat v[maxn];
int tag[maxn];
int dp[maxn][4];
int indegree[maxn];
inline bool judge(int x, int y, int flg1, int flg2)
{
int xmin;
int xmax;
if (flg1 == 1)
{
xmin = MIN(v[x].a, v[x].b);
xmax = MAX(v[x].a, v[x].b);
}
if (flg1 == 2)
{
xmin = MIN(v[x].b, v[x].c);
xmax = MAX(v[x].b, v[x].c);
}
else if (flg1 == 3)
{
xmin = MIN(v[x].a, v[x].c);
xmax = MAX(v[x].a, v[x].c);
}
int ymin;
int ymax;
if (flg2 == 1)
{
ymin = MIN(v[y].a, v[y].b);
ymax = MAX(v[y].a, v[y].b);
}
if (flg2 == 2)
{
ymin = MIN(v[y].b, v[y].c);
ymax = MAX(v[y].b, v[y].c);
}
else if (flg2 == 3)
{
ymin = MIN(v[y].a, v[y].c);
ymax = MAX(v[y].a, v[y].c);
}
if (ymin < xmin && ymax < xmax)return 1;
return 0;
}
int main()
{
scanf("%d", &T);
while (T--)
{
memset(dp, 0, sizeof(dp));
memset(H, 0, sizeof(H));
memset(NXT, 0, sizeof(NXT));
memset(indegree, 0, sizeof(indegree));
eSize = 0;
scanf("%d", &n);
for (int i = 1 ;i <= n; i++)
{
scanf("%d%d%d", &v[i].a, &v[i].b, &v[i].c);
}
for (int i = 1; i <= n; i++)
{
for (int j = i + 1; j <= n; j++)
{
for (int flg1 = 1; flg1 <= 3; flg1++)
{
for (int flg2 = 1; flg2 <= 3; flg2++)
{
if (judge(i, j, flg1, flg2))
{
indegree[j]++;
add(i, j, flg1, flg2);
}
if (judge(j, i, flg1, flg2))
{
indegree[i]++;
add(j, i, flg1, flg2);
}
}
}
}
}
queue<int> Q;
for (int i = 1; i <= n; i++)
{
if (!indegree[i])
{
Q.push(i);
}
}
while (!Q.empty())
{
int x = Q.front(); Q.pop();
dp[x][1] = MAX(dp[x][1], v[x].c);
dp[x][2] = MAX(dp[x][2], v[x].a);
dp[x][3] = MAX(dp[x][3], v[x].b);
for (int i = H[x]; i; i = NXT[i])
{
indegree[E[i].to]--;
if (E[i].flg2 == 1)
{
dp[E[i].to][1] = MAX(dp[E[i].to][E[i].flg2], dp[x][E[i].flg1] + v[E[i].to].c);
}
else if (E[i].flg2 == 2)
{
dp[E[i].to][2] = MAX(dp[E[i].to][E[i].flg2], dp[x][E[i].flg1] + v[E[i].to].a);
}
else if (E[i].flg2 == 3)
{
dp[E[i].to][3] = MAX(dp[E[i].to][E[i].flg2], dp[x][E[i].flg1] + v[E[i].to].b);
}
if (!indegree[E[i].to])
{
Q.push(E[i].to);
}
}
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
ans = MAX(ans, MAX(dp[i][1], max(dp[i][2], dp[i][3])));
}
printf("%d\n", ans);
}
}