hdu 5.2.6 3231 box relations

本文详细解析了一道关于三维空间中盒子关系的问题,利用拓扑排序的方法解决盒子间的相对位置关系,包括输入输出样例及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

默……停了好久……终于良心发现了……

Box Relations

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 84 Accepted Submission(s): 35
 
Problem Description
There are n boxes C1, C2, ..., Cn in 3D space. The edges of the boxes are parallel to the x, y or z-axis. We provide some relations of the boxes, and your task is to construct a set of boxes satisfying all these relations.

There are four kinds of relations (1 <= i,j <= ni is different from j):
  • I i j: The intersection volume of Ci and Cj is positive.
  • X i j: The intersection volume is zero, and any point inside Ci has smaller x-coordinate than any point inside Cj.
  • Y i j: The intersection volume is zero, and any point inside Ci has smaller y-coordinate than any point inside Cj.
  • Z i j: The intersection volume is zero, and any point inside Ci has smaller z-coordinate than any point inside Cj.
.
 
Input
There will be at most 30 test cases. Each case begins with a line containing two integers n (1 <= n <= 1,000) and R (0 <= R <= 100,000), the number of boxes and the number of relations. Each of the following R lines describes a relation, written in the format above. The last test case is followed by n=R=0, which should not be processed.
 
Output

            For each test case, print the case number and either the word POSSIBLE or IMPOSSIBLE. If it\\\\\\\'s possible to construct the set of boxes, the i-th line of the following n lines contains six integers x1, y1, z1, x2, y2, z2, that means the i-th box is the set of points (x,y,z) satisfying x1 <= x <= x2, y1 <= y <= y2, z1 <= z <= z2. The absolute values of x1, y1, z1, x2, y2, z2 should not exceed 1,000,000.

Print a blank line after the output of each test case.
 
Sample Input
3 2
I 1 2
X 2 3
3 3
Z 1 2
Z 2 3
Z 3 1
1 0
0 0
 
Sample Output
Case 1: POSSIBLE
0 0 0 2 2 2
1 1 1 3 3 3
8 8 8 9 9 9

Case 2: IMPOSSIBLE

Case 3: POSSIBLE
0 0 0 1 1 1
 

这题显然我是不会做的……(喂!好得意嘛!)看大家说要用拓扑排序……那……那就先看看拓扑是个啥吧……

对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前。  --百度百科

so……不如……还是直接抄代码好了………………sign

#include <iostream>
using namespace std;
#define N 2001
#define M 500000

int NE;
int n;
int head[4][N];
int q[4][N];
int degree[4][N];
int ans[4][N];

struct node
{
       int v,next;
       node(){};
       node(int a,int b)
       {
           next=a;v=b;
       }
}E[M];

void insert(int type,int u,int v)
{
     E[NE]=node(head[type][u],v);//add a new edge
     head[type][u]=NE++;
     degree[type][v]++;
}

bool topsort(int type)
{
     int front=1,top=0;
     for(int i=1;i<=2*n;i++)
     {
             if(degree[type][i]==0)
             {
                 q[type][top++]=i;
                 degree[type][i]--;
             }
     }
     while(front<top)
     {
         int u=q[type][front++];
         for(int i=head[type][u];i!=-1;i=E[i].next)
         {
                 int v=E[i].v;
                 degree[type][v]--;
                 if(degree[type][v]==0)
                 {
                     q[type][top++]=v;
                     degree[type][v]--;
                 }
         }
     }
     return top==2*n;
}

void solve()
{
     for(int i=1;i<=3;i++)
     {
             if(!topsort(i))
             {
                 cout<<"IMPOSSIBLE"<<endl;
                 return ;
             }
     }
     cout<<"POSSIBLE"<<endl;
     for(int i=1;i<=3;i++)
     {
         for(int j=0;j<2*n;j++)
         {
             ans[i][q[i][j]]=j;
         }
     }
     for(int i=1;i<=n;i++)
     {
             cout<<ans[1][i]<<" "<<ans[2][i]<<" "<<ans[3][i]<<endl;
             cout<<ans[1][i+n]<<" "<<ans[2][i+n]<<" "<<ans[3][i+n]<<endl;
     }
}

void init()
{
     NE=0;
     memset(degree,0,sizeof(degree));
     memset(head,-1,sizeof(head));
     for(int i=1;i<=n;i++)
         for(int j=1;j<=3;j++)
             insert(j,i,i+n);
}


int main()
{
    char ch[2];
    int a,b;
    int k=1;//record the number of case for print
    int m;
    while(cin>>n>>m,n||m)
    {
        init();
        while(m--)
        {
            cin>>ch>>a>>b;
            if(ch[0]=='I')
            {
                for(int i=1;i<=3;i++)
                {
                    insert(i,a,b+n);
                    insert(i,b,a+n);
                }
            }
            else
                 insert(ch[0]-'X'+1,a+n,b);
        }
        cout<<"Case "<<k++<<": ";
        solve();
        cout<<endl;
    }
}
                

居然超时了……情何以堪……重点是连超时的代码我都看不懂………………


时间静静的过去了一个多月……终于绕了一圈回到了这道题(这也是我喜欢step的地方……必须面对自己惨淡的人生啊……)差点又码一遍错的代码……这次……让我好好理解一下吧至少……话说这次错的代码交上去是system error。。。那是个毛?!

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

#define N 2002
#define M 500000

struct node{
       int ed;
       node *next;
}e[M],*head[4][N];

int pos;
int n;
int q[4][N];
int in[4][N];//number of n's in-degree
int ans[4][N];

void insert(int type,int a,int b);

void init()
{
     pos=0;
     memset(head,0,sizeof(head));
     memset(in,0,sizeof(in));
     for(int i=1;i<=n;i++)
         for(int j=1;j<=3;j++)
             insert(j,i,i+n);//every cube has its original requirement
}

void insert(int type,int a,int b)
{
     e[pos].ed=b;//the end point of the edge
     e[pos].next=head[type][a];//if have several end point
     head[type][a]=&e[pos++];//head point to now edge 
     in[type][b]++;//the end point's in-degree ++
}

bool topsort(int type)
{
    int front,top;
    front=top=0;
    for(int i=1;i<=2*n;i++)
    {
        if(!in[type][i])//no in-degree
        {
            q[type][top++]=i;//enqueue
        }
    }
    while(front<top)
    {
        int u=q[type][front++];
        for(node *p=head[type][u];p;p=p->next)//tear all the edge of the start point
        {
            in[type][p->ed]--;//tear the edge, the end point's in-degree minus
            if(!in[type][p->ed])//check if the end point has no in-degree
            {
                q[type][top++]=p->ed;//enqueue
            }
        }
    }
    return top==2*n;//all point enqueued
}


void solve()
{
    for(int i=1;i<=3;i++)
    {
        bool flag=topsort(i);
        if(!flag)
        {
            puts("IMPOSSIBLE");
            return;
        }
    }
    puts("POSSIBLE");
    for(int i=0;i<2*n;i++)
        for(int j=1;j<=3;j++)
            ans[j][q[j][i]]=i;
    for(int i=1;i<=n;i++)
        printf("%d %d %d %d %d %d\n", ans[1][i], ans[2][i], ans[3][i],ans[1][i + n], ans[2][i + n], ans[3][i + n]);
}




int main(void){  
    char ch[2];  
    int a,b;  
    int cas=1;
    int r;  
    while(cin>>n>>r,n||r){  
        init();  
        while(r--){  
            //cin>>ch>>a>>b; //if use cin...timelimit exceeded....no...
            scanf("%s %d %d", &ch, &a, &b);
            if(ch[0]=='I'){  
                for(int i=1;i<=3;i++){  
                    insert(i,a,b+n);  
                    insert(i,b,a+n);  
                }  
            }  
            else  
                insert(ch[0]-'X'+1,a+n,b);//this is great  
        }  
        printf("Case %d: ",cas++);  
        solve();  
        printf("\n");  
    }  
    return 0;
}  

算是差不多知道是怎么回事了……但让我自己写果然还是有些难吧……

用的是一个三维的拓扑排序,其实就是建一个3维数组分别加入边,排序和输出而已……

可以简化成一维的先理解下。

就是每个线段有两个端点,a+n大于a,即a端指向a+n端(共n条线段),即a->a+n。两个线段(a,b)间有两种情况。1相交,则a+n大于b,b+n大于a。2.x a b,即b大于a+n。

然后把所有的边放在一起拓扑排序~具体如下:


这样得到一个拓朴序列 v 1 , v 6 , v 4 , v 3 , v 2 , v 5 。 

是的请叫我粘贴党。

代码实现也差不多,找无入度点,找它指向的所有后续点,删边减点。这里的node中用的是next指针,指向下一个由同一起始点指向的终点。如对于1有三个终点234,则1指向的终点可能是4,而4会指向3,3会指向2。……总觉得好麻烦。

这个程序除了还有些使用困难的拓扑排序外,还有两个小点。一是cin真的要慎用。140ms到超时,就是这么可怕。二是自己脑残了居然把i和j设成全局变量!!脑子无疑是被枪打了。害我调半天混蛋- -

终于over了。5.3进军!頑張る!!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值