题意:给出几个多维的箱子,如果箱子的每一边都小于另一个箱子的对应边,那就称这个箱子小于另一个箱子,然后要求能够套出的最多的箱子。
要注意的是关系图的构建,对箱子的边排序,如果分别都小于另一个箱子就说明是箱子小于,重载<即可。
然后就是正常的dp最长路的搜索了。
代码:
/*
* Author: illuz <iilluzen[at]gmail.com>
* Blog: http://blog.csdn.net/hcbbt
* File: uva103.cpp
* Create Date: 2013-09-12 19:32:36
* Descripton: dp
*/
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 100;
struct Box {
int dem;
int e[30];
void Sort() {
sort(e, e + dem);
}
bool operator < (const Box& a) const {
for (int i = 0; i < dem; i++)
if (e[i] >= a.e[i])
return false;
return true;
}
} b[MAXN];
int big[MAXN][MAXN], k, t;
int dp[MAXN];
int solve(int i) {
if (dp[i] > 0) return dp[i];
dp[i] = 1;
for (int j = 0; j < t; j++)
if (big[i][j])
dp[i] = max(dp[i], solve(j) + 1);
return dp[i];
}
void output(int i) {
for (int j = 0; j < t; j++)
if (big[i][j] && dp[i] == dp[j] + 1) {
printf(" %d", j + 1);
output(j);
break;
}
}
int main() {
while (scanf("%d%d", &t, &k) != EOF) {
for (int i = 0; i < t; i++) {
for (int j = 0; j < k; j++) {
b[i].dem = k;
scanf("%d", &b[i].e[j]);
}
b[i].Sort();
}
memset(big, 0, sizeof(big));
memset(dp, 0, sizeof(dp));
for (int i = 0; i < t; i++)
for (int j = 0; j < t; j++)
if (i != j && b[i] < b[j])
big[i][j] = 1;
for (int i = 0; i < t; i++)
solve(i);
int tt = 0;
for (int i = 0; i < t; i++)
if (dp[i] > dp[tt])
tt = i;
printf("%d\n", dp[tt]);
printf("%d", tt + 1);
output(tt);
printf("\n");
}
return 0;
}
...
题目:UVA 103 stacking boxes 题目大意: 给你两个数,一个是盒子的个数,一个是每一个盒子的维数。将一个个盒子互相装起来,让你求最多可以装多少个,要求字典序最小。 解析:这个就是盒子的嵌套,和二维盒子嵌套有点像,只是建图的方法不一样,二维只要判断两个,长和宽即可,而k维需要判断k次,除此之外,其余都是一样的。 方法: 前提:dp[i]=max(dp[i],d(j)+1); 第一...
UVa 1289 Stacking Plates 题目 ◇题目传送门◆(由于UVa较慢,这里提供一份vjudge的链接) ◇题目传送门◆ 题目大意 有NN堆盘子,第ii堆盘子有hihi个,从上到下直径不减。有两种操作: split:将一堆盘子从某个位置分成上下两堆; join:将一堆盘子aa放在另一堆盘子bb上,要求aa底部的盘子直径不超过bb顶部盘子直径。 求将所有盘子叠成一堆的最少操作步数。 ...
拿到这道题目第一反应就是它很像汉诺塔问题,只是多了划分这个操作,因此第一步我们尝试把它简化成汉诺塔问题 首先明确一点,最终结果等于划分次数加合并次数。设划分次数为x,那么划分x次必然会形成n+x个堆,把这n+x个堆合并成1个堆需要n+x-1次合并操作,因此最终结果就是2*x+n-1,这样我们只用划分次数x就表示出了最终结果。不过为了使问题更接近汉诺塔问题,我们应该用合并次数来表示最终结果,设合并次...
题目描述: 给定n维的m个物品,按照各维长度严格递增的排序,求最长的序列,并按照字典序输出。 例如n=4,(1 2 3 4)之后是(2,3,4,5)就可以。 思维过程: 《入门经典》上DAG模型。 枚举状态结点时,出现了思维误区。想要把n维的n个长度滚动成n种状态点。 上述考虑固然可以,但是不是n种状态点,因为是按顺序排列,所以是n!种,然而n《=30。 后来想到了贪心的优化,我们的重点是一个能嵌...
题目链接:http://poj.org/problem?id=3249 题目大意:给出n个点,m条边,每个点都提供了相对的点权值,然后给出相连着的边,问从起点走到终点最大利润值。起点是入度为0的点,终点是出度为0的点。 思路1:SPFA求最长路,正向建边TLE,反向建边4400msAC。。。。 2:记忆化搜索,每次都保存当前点到终点获得的最大利润。 AC代码,搜索 ....1844ms...
P1113 杂务 传送门 题目描述 John的农场在给奶牛挤奶前有很多杂务要完成,每一项杂务都需要一定的时间来完成它。比如:他们要将奶牛集合起来,将他们赶进牛棚,为奶牛清洗乳房以及一些其它工作。尽早将所有杂务完成是必要的,因为这样才有更多时间挤出更多的牛奶。当然,有些杂务必须在另一些杂务完成的情况下才能进行。比如:只有将奶牛赶进牛棚才能开始为它清洗乳房,还有在未给奶牛清洗乳房之前不能挤奶。我们把这...
题意:有n种立方体,每种无穷个。要求选一些立方体摞成一根尽量高的柱子,使得每个立方体的底面长宽严格小于它下方立方体的底面长宽 解析:实际上每种立方体只有三次使用机会,先做预处理,给n*3种立方体编号。因为是严格小于的,所以这个图是DAG,可以套用DAG最长算法。建图,G[i][j]表示i到j有一条连线,j在i的上方。d[i]表示以i为起点的最长高度。对于底面长宽最大的立方体来说,以它为起点的长度就...
...
难度等级:3 题目:UVA - 437 The Tower of Babylon 题意: 给出n种矩形石块,有x,y,z(长宽高),有无限个,小块往大块上堆叠(严格小,即上下面积不能相同),求用这些块堆叠的最大高度。 思路: 通过第一个样例可知,一块有三用,假设x<y<z,底部面积有3种情况:①(x,y,z)②(x,z,y)③(y,z,x) 每种有无限块。题目给出n块(n<=30...