uva 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 \leN$ ) 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

一开始看到这题,我就知道这个是DAG上的dp,记得之前做过两道类似的题,uva103堆砌盒子,那道题是个多维嵌套,只有前者每个维度严格小于后者时,前者才能嵌套于后者,还有一题是uva437巴比伦塔,那题与这题非常类似,也是往上叠塔,只是巴比伦那题每块可以多次利用,因此难度比这题小。

这道题我初看是要将一个块转化成6个,但有且只能用一个,在程序里我考虑被6除,商相同算同一个,这样被6除不同的商才能递推,于是解决了一种只能用一次的问题。

但是我在写程序时还是发现了一个棘手的问题,其实是我题目的一个条件忽略了,这题还有一个条件,就是重量轻的才能放重量重的上面,不要小看这个条件,只有这个条件保证,才能使这道题化为DAG上的dp,因为这样才是无环的无向图啊,否则问题就很棘手。就像我一开始忽略这个条件,我感觉要枚举每个环的结点作为塔的底部,即dp=1;

这样发现程序写不出来了!

记忆化搜索代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#define Maxn 3010
using namespace std;

struct cube{
    int top,bottom,td;
}p[Maxn];
int tot;
int a[6],road[Maxn],dp[Maxn];
char s[][10]={"front","back","left","right","top","bottom"};
int dfs(int x){
    int &ans=dp[x];
    if(ans) return ans;
    bool flag=true;
    for(int i=(x/6+1)*6;i<tot;i++)
        if(p[x].bottom==p[i].top){
            int t=dfs(i)+1;
            if(t>ans){
                ans=t;
                road[x]=i;flag=false;
            }
        }
    if(flag) return ans=1;
    return ans;
}
int main()
{
    int n,cas=1,maxi;
    while(scanf("%d",&n),n){
        if(cas!=1) puts("");
        tot=0;
        for(int i=1;i<=n;i++){
            for(int j=0;j<6;j++){
                scanf("%d",a+j);
                p[tot++]=cube{a[j],0,j};
            }
            for(int j=1;j<=6;j++)
                if(j&1) p[tot-j].bottom=a[5-j];
                else p[tot-j].bottom=a[7-j];
        }
        int ans=0;
        memset(dp,0,sizeof dp);
        for(int i=0;i<tot;i++)
            if(dp[i]==0) dfs(i);
        for(int j=0;j<tot;j++)
            if(dp[j]>ans){ans=dp[j];maxi=j;}
        printf("Case #%d\n%d\n",cas++,ans);
        for(int i=ans;i>0;i--){
            printf("%d %s\n",maxi/6+1,s[p[maxi].td]);
            maxi=road[maxi];
        }
    }
	return 0;
}

递推代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#define Maxn 3010
using namespace std;

struct cube{
    int top,bottom,td;
}p[Maxn];
int tot;
int a[6],road[Maxn],dp[Maxn];
char s[][10]={"front","back","left","right","top","bottom"};
int main()
{
    int n,cas=1,maxi;
    while(scanf("%d",&n),n){
        if(cas!=1) puts("");
        tot=0;
        for(int i=1;i<=n;i++){
            for(int j=0;j<6;j++){
                scanf("%d",a+j);
                p[tot++]=cube{a[j],0,j};
            }
            for(int j=1;j<=6;j++)
                if(j&1) p[tot-j].bottom=a[5-j];
                else p[tot-j].bottom=a[7-j];
        }
        for(int i=0;i<tot;i++) dp[i]=1;
        for(int i=tot-7;i>=0;i--){
            for(int j=(i/6+1)*6;j<tot;j++)
                if(p[i].bottom==p[j].top&&dp[j]+1>dp[i]){
                    dp[i]=dp[j]+1;
                    road[i]=j;
                }
        }
        int ans=0;
        for(int j=0;j<tot;j++)
            if(dp[j]>ans){ans=dp[j];maxi=j;}
        printf("Case #%d\n%d\n",cas++,ans);
        for(int i=ans;i>0;i--){
            printf("%d %s\n",maxi/6+1,s[p[maxi].td]);
            maxi=road[maxi];
        }
    }
	return 0;
}

如果觉得化成一维吃力的话,可以加一维来dp,可以参考点击打开链接


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Marching Cubes算法是一种常用的三维体数据表面重建算法。它可以将一个体数据集转化为连续的多边形网格模型。 在三维体数据中,每个体素的值表示其在某一属性上的特征,如密度、压力等。Marching Cubes算法首先将整个体数据集划分为无数个小立方体,每个小立方体包含8个顶点。然后根据每个小立方体顶点所代表的属性值与事先设定的阈值进行比较,确定该顶点是否在表面上。若在表面上,就将相应顶点连接起来组成一个面,并将该面连接到整个网格模型上。 得到的多边形网格模型可以用于可视化、仿真和分析等应用。Marching Cubes算法具有简单、高效的特点,适用于各种不规则的三维体数据集。它广泛应用于医学图像处理、地质勘探、计算机动画等领域。 然而,Marching Cubes算法也存在一些限制。首先,它在重建过程中产生的多边形可能存在不连续性和拓扑错误。为了解决这个问题,后续研究提出了一些改进算法,如Dual Marching Cubes和Extended Marching Cubes。其次,Marching Cubes算法对数据集的分辨率要求较高,对于过于细致的结构可能无法很好地重建。 总的来说,Marching Cubes算法在三维体数据表面重建领域具有重要的应用价值,其简单、高效的特点使其成为一种常用的算法。随着相关技术的不断发展,对Marching Cubes算法的改进和优化将进一步推动其在各个领域的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值