首页 > 代码库 > UVA 10051 --Tower of Cubes +dp

UVA 10051 --Tower of Cubes +dp

先将立方体按重量从大到小排序,然后就转成了类似于最长上升子序列的问题;

定义状态dp[i][j]表示以第i个立方体的第j面作为顶面时的最大高度。

则dp[i][j]=max(dp[k][d]+1;1<=k<=i-1,m[i][5-j]==m[d][k])

注意为了方便后面的状态判定,我们在输入的时候要使得相对的面的坐标和为一个常数5.

对于路径输出,我们可以采用记录父节点的方法。


代码如下:


#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

int m[550][10],dp[550][10];
int n,Case;
string face[]={"front","left","top","bottom","right","back"};

typedef struct
{
    int x,y;
}F;
F fa[550][550];

void input()
{
    for(int i=n;i>=1;i--)
    {
        for(int j=0;j<=2;j++)
        {
            scanf("%d",&m[i][j]);
            scanf("%d",&m[i][5-j]);
        }
    }
}

void print(int ans,int x,int y)
{
    printf("Case #%d\n",++Case);
    printf("%d\n",ans);
    while(x!=-1&&y!=-1)
    {
        printf("%d ",n-x+1);
        cout<<face[y]<<endl;
        int x1=fa[x][y].x;
        y=fa[x][y].y;
        x=x1;
    }
}

void solve_dp()
{
    memset(dp,0,sizeof(dp));
    memset(fa,-1,sizeof(fa));
    for(int i=1;i<=n;i++)
      for(int j=0;j<=5;j++)
         dp[i][j]=1;
    for(int i=1;i<=n;i++)
      for(int j=0;j<=5;j++)
      {
          int x=-1,y=-1;
          for(int k=1;k<=i-1;k++)
          {
              for(int d=0;d<6;d++)
              {
                  if(m[i][5-j]==m[k][d]&&dp[i][j]<dp[k][d]+1)
                  {
                      dp[i][j]=dp[k][d]+1;
                      x=k; y=d;
                  }
              }
          }
          fa[i][j].x=x; fa[i][j].y=y;
      }
    int ans=0,x,y;
    for(int i=1;i<=n;i++)
      for(int j=0;j<6;j++)
      {
          if(dp[i][j]>ans)
             ans=dp[i][j],x=i,y=j;
      }
    print(ans,x,y);
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(!n)
           break;
        if(Case!=0)
          printf("\n");
        input();
        solve_dp();
    }
  return 0;
}


UVA 10051 --Tower of Cubes +dp