poj1128 Frame Stacking

Frame Stacking
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 3636 Accepted: 1204

Description

Consider the following 5 picture frames placed on an 9 x 8 array.
........ ........ ........ ........ .CCC....

EEEEEE.. ........ ........ ..BBBB.. .C.C....

E....E.. DDDDDD.. ........ ..B..B.. .C.C....

E....E.. D....D.. ........ ..B..B.. .CCC....

E....E.. D....D.. ....AAAA ..B..B.. ........

E....E.. D....D.. ....A..A ..BBBB.. ........

E....E.. DDDDDD.. ....A..A ........ ........

E....E.. ........ ....AAAA ........ ........

EEEEEE.. ........ ........ ........ ........

    1        2        3        4        5   

Now place them on top of one another starting with 1 at the bottom and ending up with 5 on top. If any part of a frame covers another it hides that part of the frame below.

Viewing the stack of 5 frames we see the following.
.CCC....

ECBCBB..

DCBCDB..

DCCC.B..

D.B.ABAA

D.BBBB.A

DDDDAD.A

E...AAAA

EEEEEE..






In what order are the frames stacked from bottom to top? The answer is EDABC.

Your problem is to determine the order in which the frames are stacked from bottom to top given a picture of the stacked frames. Here are the rules:

1. The width of the frame is always exactly 1 character and the sides are never shorter than 3 characters.

2. It is possible to see at least one part of each of the four sides of a frame. A corner shows two sides.

3. The frames will be lettered with capital letters, and no two frames will be assigned the same letter.

Input

Each input block contains the height, h (h<=30) on the first line and the width w (w<=30) on the second. A picture of the stacked frames is then given as h strings with w characters each.
Your input may contain multiple blocks of the format described above, without any blank lines in between. All blocks in the input must be processed sequentially.

Output

Write the solution to the standard output. Give the letters of the frames in the order they were stacked from bottom to top. If there are multiple possibilities for an ordering, list all such possibilities in alphabetical order, each one on a separate line. There will always be at least one legal ordering for each input block. List the output for all blocks in the input sequentially, without any blank lines (not even between blocks).

Sample Input

9
8
.CCC....
ECBCBB..
DCBCDB..
DCCC.B..
D.B.ABAA
D.BBBB.A
DDDDAD.A
E...AAAA
EEEEEE..

Sample Output

EDABC
 
     这题和上一篇博客的那道题的做法差不多,就是建图比较麻烦。还有题目保证至少存在一种符合要求的序列,当有多种情况时按字典序由小到大输出所有的情况。
     这题的难点是输出所有的拓扑序列,根据题目描述最坏情况有26!中情况(即每一个图片都无重叠部分),刚开始就被它给吓着了,迟迟不敢下手!最后无奈之下暴力的试了一下竟然过了。只能说这题数据太水了,不过话说如果不是这样的话,这题我还真不知道怎么解了,毕竟按照暴力的方法时间复杂度太高了(欢迎哪位大神来分享下较好的算法)。
     对于建图,如果不懂的话,可以参照我的上一篇博客,然后最后求拓扑序列就是直接枚举全排列了。对于每一种排列,如果每条边都是从左到右则符合。这题其实也没用求拓扑的算法,主要是根据它的定义做个判断。
#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
int w,h;
char image[35][35];
int map[35][35];//邻接表
int flag[26];//记录字母是否出现过
int q[30],cnt;//出现的字母(由小到大)
int visit[30];//dfs时的标记数组
int ans[30];//序列

void build()
{
    int i,j,k,l;
    for(i=1;i<=h;i++)
        for(j=1;j<=w;j++)
        {
            char c=image[i][j];
            if(c=='.')
                continue;
            if(!flag[c-'A'])
            {
                int c1,c2,r;//分别记录左边界、右边界、下边界
                flag[c-'A']=1;
                //左边界
                for(k=1;;k++)
                {
                    for(l=i;l<=h;l++)
                        if(image[l][k]==c)
                            break;
                    if(l<=h)
                        break;
                }
                c1=k;
                //右边界
                for(k=w;;k--)
                {
                    for(l=i;l<=h;l++)
                        if(image[l][k]==c)
                            break;
                    if(l<=h)
                        break;
                }
                c2=k;
                //下边界
                for(k=h;;k--)
                {
                    for(l=c1;l<=c2;l++)
                        if(image[k][l]==c)
                            break;
                    if(l<=c2)
                        break;
                }
                r=k;
                //开始扫描框架上的元素
                for(k=c1;k<=c2;k++)
                {
                    int u=c-'A';
                    int v=image[i][k]-'A';
                    if(u!=v)
                        map[u][v]=1;
                    v=image[r][k]-'A';
                    if(u!=v)
                        map[u][v]=1;
                }
                for(k=i;k<=r;k++)
                {
                    int u=c-'A';
                    int v=image[k][c1]-'A';
                    if(u!=v)
                        map[u][v]=1;
                    v=image[k][c2]-'A';
                    if(u!=v)
                        map[u][v]=1;
                }
            }
        }
}
//判断每种排列是否是拓扑序列
void dfs(int i)
{
    if(i==cnt)
    {
        for(int j=0;j<cnt;j++)
            printf("%c",ans[j]+'A');
        printf("\n");
        return;
    }
    for(int j=0;j<cnt;j++)
        if(!visit[q[j]])
        {
            ans[i]=q[j];
            bool state=true;
            for(int k=i;k>0&&state;k--)
                for(int l=0;l<k;l++)
                    if(map[ans[k]][ans[l]])
                    {
                        state=false;
                        break;
                    }
            if(!state)
                continue;
            visit[q[j]]=1;
            dfs(i+1);
            visit[q[j]]=0;
        }
}

int main()
{
    int i,j;
    while(~scanf("%d%d",&h,&w))
    {
        for(i=1;i<=h;i++)
        {
            getchar();
            for(j=1;j<=w;j++)
                image[i][j]=getchar();
        }
        memset(map,0,sizeof(map));
        memset(flag,0,sizeof(flag));
        build();//建图
        cnt=0;
        for(i=0;i<26;i++)
            if(flag[i])
            {
                q[cnt++]=i;
                visit[i]=0;
            }
        dfs(0);//枚举
    }
    return 0;
}

发布了117 篇原创文章 · 获赞 45 · 访问量 17万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章