POJ 1128 & ZOJ 1083 Frame Stacking (拓扑排序)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=83

http://poj.org/problem?id=1128


Frame Stacking

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 4102   Accepted: 1378

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

题意:

给出若干张图片(矩形边框)叠在一起的效果图,保证边框为一个字符宽度,边长不短于3个字符,每条边都能看见一部分,每张图有且仅有一种字母且不重复,求出其从底到顶的叠放顺序,如果有多个解,按字典序输出每个解。题目保证有解。

分析:

首先要从凌乱的效果图中把每张图的信息抠出来,因为每条边保证可见,所以只要扫描四条边就行,得到了四条边的位置,就能确定某张图的位置。

图叠在一起只能看见每个位置顶部的图,也就是该位置有可能出现的图都在顶部那张图的下面,比如在(1,1)有A,B,C,D四张图,我们只能看见A,那么A在B,C,D的上面,即能确定A与B,C,D的相对位置。这样扫描全图,就能得到若干相对位置的信息。然后我们要得到一个合法的序列,即满足这些相对位置的信息,显然就是一个拓扑排序了。

题目要求的是所有的拓扑排序,且是字典序。由于点很少,那么就采用稍微暴力一点的方法。让我们先想一想如何求拓扑序。入度为0的点入栈/队,栈顶/队首元素出栈并进入拓扑序,然后删除其出边,如果有点的入度变成0,就把该点入栈/队,如此循环即可。我们仔细体会一下其中的过程:如果两个元素同时在栈/队中,那么他们之间的相对位置是无所谓的,这样就是多解的情况。如果要字典序最小的那组解,我们每次出栈/队的元素就是栈/队中最小的元素,这时候我们当然可以用优先队列来处理,由于这里点很少,索性就用一个数组标记哪些点可选(在栈/队中),然后遍历选择。多解的情况就有点像全排列了,想一想全排列该如何解,当然是回溯啦,这里我们用类似的方式进行深度优先搜索,就能按字典序得出所有的拓扑序了。

/*
 *
 *	Author	: 	fcbruce
 *
 *	Date	:	2014-08-10 09:39:26
 *
 */
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <cctype>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10
#define maxm
#define maxn 

using namespace std;

int h,w,n;
int L[30],R[30],U[30],D[30];
char MAP[33][33];
int fir[33][33];
int rec[33][33][30];
bool G[33][33];
int deg[33];
int topo[33];
bool pending[33];

void add_edge(int x,int y,int v)
{
	for (int i=0;i<fir[x][y];i++)
		if (rec[x][y][i]!=v && !G[rec[x][y][i]][v])
		{
			G[rec[x][y][i]][v]=true;
			deg[v]++;
		}

}

void init()
{
	memset(L,-1,sizeof L);
	memset(R,-1,sizeof R);
	memset(U,-1,sizeof U);
	memset(D,-1,sizeof D);

	for (int i=0;i<h;i++)
	{
		for (int j=0;j<w;j++)
		{
			if (isalpha(MAP[i][j]) && U[MAP[i][j]-'A']==-1)
				U[MAP[i][j]-'A']=i;
		}
	}

	for (int i=h-1;i>=0;i--)
	{
		for (int j=0;j<w;j++)
		{
			if (isalpha(MAP[i][j]) && D[MAP[i][j]-'A']==-1)
				D[MAP[i][j]-'A']=i;
		}
	}

	for (int i=0;i<w;i++)
	{
		for (int j=0;j<h;j++)
		{
			if (isalpha(MAP[j][i]) && L[MAP[j][i]-'A']==-1)
				L[MAP[j][i]-'A']=i;
		}
	}

	for (int i=w-1;i>=0;i--)
	{
		for (int j=0;j<h;j++)
		{
			if (isalpha(MAP[j][i]) && R[MAP[j][i]-'A']==-1)
				R[MAP[j][i]-'A']=i;
		}
	}
}

void build()
{
	memset(fir,0,sizeof fir);

	for (int i=0;;i++)
	{
		n=i;
		if (L[i]==-1)	break;

		for (int j=L[i];j<=R[i];j++)
		{
			rec[U[i]][j][fir[U[i]][j]++]=i;
			rec[D[i]][j][fir[D[i]][j]++]=i;
		}

		for (int j=U[i]+1;j<D[i];j++)
		{
			rec[j][L[i]][fir[j][L[i]]++]=i;
			rec[j][R[i]][fir[j][R[i]]++]=i;
		}
	}

	memset(G,0,sizeof G);
	memset(deg,0,sizeof deg);

	for (int i=0;i<h;i++)
	{
		for (int j=0;j<w;j++)
		{
			add_edge(i,j,MAP[i][j]-'A');
		}
	}
}

int st[33];

void write()
{
	for (int i=0;i<n;i++)
		putchar( st[i]+'A');
	putchar ( '\n');
}

void toposort(int x,int top)
{
	st[++top]=x;
	if (top==n-1)
	{
		write();
		return ;
	}

	for (int i=0;i<n;i++)
	{
		if (G[x][i])
		{
			deg[i]--;
			if (deg[i]==0)	pending[i]=true;
		}
	}

	for (int i=0;i<n;i++)
	{
		if (pending[i])
		{
			pending[i]=false;
			toposort(i,top);
			pending[i]=true;
		}
	}

	for (int i=0;i<n;i++)
	{
		if (G[x][i])
		{
			deg[i]++;
			if (deg[i]!=0)	pending[i]=false;
		}
	}
}

int main()
{
	#ifndef ONLINE_JUDGE
		freopen("/home/fcbruce/文档/code/t","r",stdin);
	#endif // ONLINE_JUDGE

	while (~scanf ( "%d%d",&h,&w))
	{
		for (int i=0;i<h;i++)
		{
			scanf( "%s",MAP[i]);
		}

		init();

		build();

		memset(pending,0,sizeof pending);

		for (int i=0;i<n;i++)
		{
			if (deg[i]==0)
			{
				pending[i]=true;
			}
		}

		for (int i=0;i<n;i++)
		{
			if (pending[i])
			{
				pending[i]=false;
				toposort(i,-1);
				pending[i]=true;
			}
		}
	}

	return 0;
}

POJ 1128 & ZOJ 1083 Frame Stacking (拓扑排序)

时间: 2024-08-05 10:44:11

POJ 1128 & ZOJ 1083 Frame Stacking (拓扑排序)的相关文章

POJ 2367:Genealogical tree(拓扑排序)

Genealogical tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2738 Accepted: 1838 Special Judge Description The system of Martians' blood relations is confusing enough. Actually, Martians bud when they want and where they want. They ga

[poj 1691] Painting A Board dfs+拓扑排序

Painting A Board Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 3611 Accepted: 1795 Description The CE digital company has built an Automatic Painting Machine (APM) to paint a flat board fully covered by adjacent non-overlapping rectangle

POJ 1094-Sorting It All Out(拓扑排序)

Sorting It All Out Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28055   Accepted: 9689 Description An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from sm

POJ 1094 Sorting It All Out 拓扑排序

Sorting It All Out Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%lld & %llu Description An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to

UVA 124 &amp; POJ 1270 Following Orders(拓扑排序)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=60 http://poj.org/problem?id=1270 Following Orders Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3806   Accepted: 1507 Description Or

hello大家好,我是拓扑排序

发几个以前写的拓扑排序,回顾一下. 拓扑排序,一般不会单独考,主要要求还是掌握好这个概念,有个感性的认识,以及能快速的写出求拓扑排序的程序,进而继续接下来对图的处理,或是比如dp之类的算法,又或者是判断有无环之类.求拓扑序主要就是运用队列,push入度为0的点,删掉它们出去的边,重复这个操作.像要是求字典序最小,就可以用优先队列. TOJ 3993 求字典序最小的拓扑排序 1 #include<cstdio> 2 #include<queue> 3 #include<cstr

算法总结之拓扑排序

拓扑排序 1.一般应用       拓扑排序常用来确定一个依赖关系集中,事物发生的顺序.例如,在日常工作中,可能会将项目拆分成A.B.C.D四个子部分来完成,但A依赖于B和D,C依赖于D.为了计算这个项目进行的顺序,可对这个关系集进行拓扑排序,得出一个线性的序列,则排在前面的任务就是需要先完成的任务. 2.实现的基本方法 (1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它. (2)从网中删去该顶点,并且删去从该顶点发出的全部有向边. (3)重复上述两步,直到剩余的网中不再存在没有前趋

Frame Stacking ZOJ 1083,poj 1128

Frame Stacking Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4034   Accepted: 1352 Description Consider the following 5 picture frames placed on an 9 x 8 array. ........ ........ ........ ........ .CCC.... EEEEEE.. ........ ........ ..

POJ 1128 Frame Stacking(拓扑排序&amp;#183;打印字典序)

题意  给你一些矩形框堆叠后的鸟瞰图  推断这些矩形框的堆叠顺序  每一个矩形框满足每边都至少有一个点可见  输入保证至少有一个解 按字典序输出全部可行解 和上一题有点像  仅仅是这个要打印全部的可行方案  建图还是类似  由于每一个矩形框的四边都有点可见  所以每一个矩形框的左上角和右下角的坐标是能够确定的  然后一个矩形框上有其他字符时  就让这个矩形框相应的字符和那个其他字符建立一个小于关系  由于要打印方案  所以在有多个入度为0的点时须要用DFS对每种选择都进行一遍拓扑排序 #incl