2013-07-05 11:15:41Morris

[UVA][LIS] 10051 - Tower of Cubes


  Problem A: Tower of Cubes 

In this problem you are given N colorful cubes each having a distinct weight. Each face of a cube is colored with one color. Your job is to build a tower using the cubes you have subject to the following restrictions:

  • Never put a heavier cube on a lighter one.
  • The bottom face of every cube (except the bottom cube, which is lying on the floor) must have the same color as the top face of the cube below it.
  • Construct the tallest tower possible.

Input 

The input may contain multiple test cases. The first line of each test case contains an integer N ( $1 le N le 500$) indicating the number of cubes you are given. The i­th ( $1 le i le
N$) of the next N lines contains the description of the i­th cube. A cube is described by giving the colors of its faces in the following order: front, back, left, right, top and bottom face. For your convenience colors are identified by integers in the range 1 to 100. You may assume that cubes are given in the increasing order of their weights, that is, cube 1 is the lightest and cube N is the heaviest.

The input terminates with a value 0 for N.

Output 

For each test case in the input first print the test case number on a separate line as shown in the sample output. On the next line print the number of cubes in the tallest tower you have built. From the next line describe the cubes in your tower from top to bottom with one description per line. Each description contains an integer (giving the serial number of this cube in the input) followed by a single white­space character and then the identification string (front, back, left, right, top or bottom) of the top face of the cube in the tower. Note that there may be multiple solutions and any one of them is acceptable.

Print a blank line between two successive test cases.

Sample Input 

3
1 2 2 2 1 2
3 3 3 3 3 3
3 2 1 1 1 1
10
1 5 10 3 6 5
2 6 7 3 6 9
5 7 3 2 1 9
1 3 3 5 8 10
6 6 2 2 4 4
1 2 3 4 5 6
10 9 8 7 6 5
6 1 2 3 4 7
1 2 3 3 2 1
3 2 1 1 2 3
0

Sample Output 

Case #1
2
2 front
3 front
 
Case #2
8
1 bottom
2 back
3 right
4 left
6 top
8 front
9 front
10 top



Miguel Revilla
2000-12-28

題目描述:

有一些積木,現在把它疊起來,相鄰兩面要具有相同數字,且越上層的積木重量越輕,
題目已經給定重量由輕到重,問最長可以多長,並且把疊的方式印出來。
題目給定的順序由輕到重,輸出的時候印出哪面朝上,給定的時候六個數字分別是
front, back, left, right, top or bottom

題目解法:
明顯是個 LIS 的題目,但由於要考慮兩面相同的時候去接,因此會多六個狀態,因此會有
dp[i][j] j 為哪一面朝上,在轉移的時候要檢查 j 相對應的面上數字為何。

O(n^2 * 36)

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int A[505][6];
int dp[505][6];
int argdp[505][6][2];
int trans(int x) {
    if(x == 0)  return 1;
    if(x == 1)  return 0;
    if(x == 2)  return 3;
    if(x == 3)  return 2;
    if(x == 4)  return 5;
    if(x == 5)  return 4;
    return -1;
}
void print(int x, int y) {
    if(dp[x][y]) {
        print(argdp[x][y][0], argdp[x][y][1]);
    }
    printf("%d ", x+1);
    if(y == 0)  puts("front");
    else if(y == 1) puts("back");
    else if(y == 2) puts("left");
    else if(y == 3) puts("right");
    else if(y == 4) puts("top");
    else puts("bottom");
}
int main() {
    int n, i, j, k, p, q, cases = 0;
    while(scanf("%d", &n) == 1 && n) {
        for(i = 0; i < n; i++)
            for(j = 0; j < 6; j++)
                scanf("%d", &A[i][j]);
        memset(dp, 0, sizeof(dp));
        for(i = 0; i < n; i++) {
            for(j = i+1; j < n; j++) {
                for(p = 0; p < 6; p++) {//bottom face
                    for(q = 0; q < 6; q++) {//top face
                        if(A[i][p] == A[j][q]) {
                            int x = trans(p);
                            if(dp[i][x]+1 > dp[j][q]) {
                                dp[j][q] = dp[i][x]+1;
                                argdp[j][q][0] = i;
                                argdp[j][q][1] = x;
                            }
                        }
                    }
                }
            }
        }
        int ret = 0;
        for(i = 0; i < n; i++)
            for(j = 0; j < 6; j++)
                ret = max(ret, dp[i][j]);
        if(cases)   puts("");
        printf("Case #%d\n", ++cases);
        printf("%d\n", ret+1);
        int x, y;
        for(i = 0; i < n; i++)
            for(j = 0; j < 6; j++)
                if(dp[i][j] == ret)
                    x = i, y = j;
        print(x, y);
    }
    return 0;
}