拓撲排序 POJ1128 Frame Stacking

拓撲排序 POJ1128 Frame Stacking

拓撲排序:
有向無環圖的拓撲排序
基本算法:
無前驅的定點優先Turpo排序算法是每一步總輸出當前無前驅(入度爲零)的定點。
(1)從有向圖中選擇一個沒有前驅的頂點並輸出它
(2)從網中刪除該頂點,並刪除從該定點出發的所有有向邊和有向邊鏈接的對應頂點
(3)重複上述步驟直到剩餘網絡中不再存在沒有前驅的頂點

性質:
(1)剩餘的點一定構成環路
(2)時間複雜度:
圖:G(n,m)
用鄰接表存:O(n+m)

實現:
用隊列實現

本題擴展:
(1)輸出所有拓撲排序
dfs:用can數組代替隊列。
(a)用數組can[MAXN]記錄所有的可以被選擇的結點
(b)dfs過程中依據字典序選擇結點
(c)將入度爲零的點i設爲can[i]爲true

題目:
題目原文

Frame Stacking
Time Limit: 1000MS

Memory Limit: 10000K
Total Submissions: 5641

Accepted: 1971
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
Source
Southern African 2001
#include <iostream>
#include <cstdio> 
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 40;
const int INF = 0x7fffffff;

int h;
int w;
int highest;
int lowest;
int leftest;
int rightest;
int tot;
int du[MAXN];
char map[MAXN][MAXN];
bool used[30];
int used2[MAXN];
int can[MAXN];
int choose[MAXN];

void init() {
    memset(du, 0, sizeof du);
    memset(used, 0, sizeof used);
    memset(can, 0, sizeof can);
    memset(choose, 0, sizeof choose);
}

struct Link {
    int node;
    Link* next;
    void push_back(int k) {
        Link* p = new Link;
        p->node = k;
        p->next = next;
        next = p;
    }
}tu[30];

void search(char tip) {
    for (int i = 1; i <= h; ++i) 
        for (int j = 1; j <= w; ++j) 
            if (map[i][j] == tip) {
                highest = min(highest, i);
                lowest = max(lowest, i);
                leftest = min(leftest, j);
                rightest = max(rightest, j);        
            }
}

void build(char tip) {
    memset(used2, 0, sizeof used2);
    for (int i = highest; i <= lowest; ++i) {
        if (!used2[map[i][leftest]-'A'] && map[i][leftest] != tip)
            tu[tip-'A'].push_back(map[i][leftest]-'A');
        if (!used2[map[i][rightest]-'A'] && map[i][rightest] != tip)
            tu[tip-'A'].push_back(map[i][rightest]-'A');
        used2[map[i][leftest]-'A'] = used2[map[i][rightest]-'A'] = true;
    }
    for (int i = leftest; i <= rightest; ++i) {
        if (!used2[map[highest][i]-'A'] && map[highest][i] != tip)
            tu[tip-'A'].push_back(map[highest][i]-'A');
        if (!used2[map[lowest][i]-'A'] && map[lowest][i] != tip) 
            tu[tip-'A'].push_back(map[lowest][i]-'A');
        used2[map[highest][i]-'A'] = used2[map[lowest][i]-'A'] = true;
    }   
}

void dfs(int tip) {
    if (tip > tot) {
        for (int i = 1; i <= tot; ++i)
            printf("%c", choose[i] + 'A');
        printf("\n");
        return;
    } 
    for (int i = 0; i < 26; ++i) {
        if (can[i]) {
            choose[tip] = i;
            can[i] = false;
            for (Link* j = tu[i].next; j; j = j->next) {
                du[j->node]--;
                if (du[j->node] == 0)
                    can[j->node] = true;
            }
            dfs(tip + 1);
            for (Link* j = tu[i].next; j; j = j->next) {
                du[j->node]++;
                can[j->node] = false;
            }
            can[i] = true;
        }
    }
}

void Turpo() {
    for (int i = 0; i < 26; ++i)
        if (used[i])
            for (Link* j = tu[i].next; j; j = j->next)
                du[j->node]++;
    tot = 0;
    for (int i = 0; i < 26; ++i)
        if (used[i])
            ++tot;
    for (int i = 0; i < 26; ++i)
        if (used[i] && du[i] == 0)
            can[i] = true;
    dfs(1);
}

int main()
{
    while (~scanf("%d%d", &h, &w)) {
        init();
        for (int i = 1; i <= h; ++i)
            scanf("%s", &map[i][1]);
        for (int i = 0; i <= 26; ++i)
            tu[i].next = NULL;
        for (int i = 1; i <= h; ++i) 
            for (int j = 1; j <= w; ++j)
                if (map[i][j] != '.' && !used[map[i][j]-'A']) {
                    used[map[i][j] - 'A'] = true;
                    highest = INF;
                    lowest = 0;
                    leftest = INF;
                    rightest = 0;
                    search(map[i][j]);
                    build(map[i][j]);
                }
        Turpo();
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章