题目链接:http://acm.ocrosoft.com/problem.php?id=1246
题目描述:
下图为5个放置在9x8 的点阵中的方框图:
若将他们按顺序叠放起来.则会有某些框的一部分盖住了另外一个框,遮住一些部分.
下图是这5个框叠放起来的图形:
那么这些方框从下至上叠放的顺序是什么呢?
答案是: EDABC.
你的任务是对于一个给定的方框叠放以后的图形, 找出他们从下至上的叠放顺序.
下面是一些规则:
(1). 方框的边宽度为一个字符,边长不少于3个字符;
(2). 每个方框的4条边都有一部分可见, 一个角代表两条边;
(3). 方框用大写字母了表示, 没有两个方框用相同的字符来表示.
输入格式
前两行每行一个数字,分别表示长、宽。
接下来为框叠起来的图。没有框的地方用'.'表示。
输出格式
输出全部可能情况。
按字典顺序排序。
样例1
样例输入1
9
8
.CCC....
ECBCBB..
DCBCDB..
DCCC.B..
D.B.ABAA
D.BBBB.A
DDDDAD.A
E...AAAA
EEEEEE..
Copy
样例输出1
EDABC
思路:
首先因为每个字母矩形顶角都一定是有的,所以我们可以先求出左上和右下角两个顶角。然后就可以确定下这个矩形的形状了,然后沿着四条边扫描一遍,如果有一个字母c在当前字母k矩阵上面,那么说明c一定是在k上面的,那么肯定有在输出顺序中c要在k后面。
然后就是拓扑排序。用book[i][j]记录有向边,那么很容易就变成一个求所有拓扑序列的问题了。因为序列要从小到大字典序,而且要输出全部的情况,所以我们考虑dfs即可。
代码:
#include<bits/stdc++.h>
using namespace std;
int n, m;
char a[50][50];//存储初始方阵
char ans[50];//记录答案
int book[50][50];//记录有向路径
int in[50];//记录c字符前面有几个字符
int h[50];//记录某个字母有没有用到
int cnt;//记录方阵中有几个字母
void dfs(int cur)
{
if (cur == cnt)
{
cout << ans << endl;
}
else
{
for (int i = 0; i < 26; i++)
{
if (in[i] == 0 && h[i])//如果该字母没有前缀了且这个字母被输入过
{
ans[cur] = i + 'A';
in[i] = -1;//这个字母前面没有字母了
for (int j = 0; j < 26; j++)
{
if (book[i][j])
{
in[j]--;//所有用这个字母的前面都要少1
}
}
dfs(cur + 1);
in[i] = 0;//回溯
for (int j = 0; j < 26; j++)
{
if (book[i][j])
{
in[j]++;//所有用这个字母的前面都要加1
}
}
}
}
}
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> a[i][j];
}
}
for (int k = 0; k < 26; k++)//26个字母遍历一遍
{
char ch = 'A' + k;//遍历的那个字母赋值给ch
int x1 = 50, y1 = 50, x2 = 0, y2 = 0;
for (int i = 1; i <= n; i++)//求出遍历的那个图案的左上角和右下角
{
for (int j = 1; j <= m; j++)
{
if (a[i][j] == ch)
{
x1 = min(x1, i), y1 = min(y1, j);
x2 = max(x2, i), y2 = max(y2, j);
}
}
}
if (x1 == 50 || y1 == 50 || x2 == 0 || y2 == 0)//保持原样说明没有这个字母,直接到下一个循环
{
continue;
}
h[k] = 1;//表示这个字母输入过
cnt++;//输入的总字母++
for (int i = x1; i <= x2; i++)
{
for (int j = y1; j <= y2; j++)
{
if (i == x1 || i == x2 || j == y1 || j == y2)
{
if (a[i][j] != ch && a[i][j] != '.')//不是k字母那就说明该字母在k字母的后面
{
int c = a[i][j] - 'A';
if (!book[k][c])
{
book[k][c] = 1;//k到c是可行的
in[c]++;//c的前面有in[c]个字母
}
}
}
}
}
}
dfs(0);
}