题目:给你n个正方体,每个面有一种颜色,他们按照重量递增的方式排列着,现在要求把他们排成一个塔,
每层一个正方体,要求每个正方体上面的正方体的重量全都小于他,还要保证接触的面上的颜色相同,
问最高能摆放多少层,答案不唯一。
分析:dp,动态规划,lis。最大不下降子序列,已经排好序,满足接触的面颜色相同即可。
定义状态:f(i,k)为以第i个方块作为顶时,k面朝上时的最大高度;
转移方程:f(i,k)= max(f(j,f)) { j < i,且相接处的面相同 };
每个方块有6中摆放法式,利用一维数组压缩状态记录前驱,输出路径。
说明:去反面直接异或操作即可,好久没刷题了╮(╯▽╰)╭。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int cubes[505][6];
int length[505][6];
int front[3333];
char face[6][7] = {"front", "back", "left", "right", "top", "bottom"};
void output(int space, int n)
{
if (space) {
printf("%d %s\n",n-space/6,face[space%6]);
output(front[space], n);
}
}
int main()
{
int n,t = 0;
while (~scanf("%d",&n) && n) {
for (int i = n; i >= 1; -- i) {
for (int j = 0; j < 6; ++ j) {
scanf("%d",&cubes[i][j]);
}
}
int max = 0,space = 0;
for (int i = 1; i <= n; ++ i) {
for (int k = 0; k < 6; ++ k) {
length[i][k] = 1;
front[6*i+k] = 0;
for (int j = 1; j < i; ++ j) {
for (int f = 0; f < 6; ++ f) {
if (cubes[j][f] == cubes[i][k^1]
&& length[j][f] >= length[i][k]) {
length[i][k] = length[j][f]+1;
front[6*i+k] = 6*j+f;
}
}
}
if (max < length[i][k]) {
max = length[i][k];
space = 6*i+k;
}
}
}
if (t ++) printf("\n");
printf("Case #%d\n",t);
printf("%d\n",max);
output(space, n+1);
}
return 0;
}