传送门:http://poj.org/problem?id=1128
这题是poj2585加强版,那题是固定图案,而这题是只给你图,求顺序,乍看这题挺难的,但是用2585的思路来处理,两题其实没有什么不同,同样对于每个覆盖的点进行建图,然后建立完一个有向图之后拓扑排序。
这题的重点就是如何确定一个矩阵的位置,我用了map<char,结构体>来记录当前字母的左上角坐标与右下角坐标,那么就能迅速知道每个字母分别覆盖了那些位置,再建图就容易了。
这题还有个坑点,就是如果有多种答案的话,要字典序输出所有解,所以在拓扑的时候要用dfs来写。
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<time.h>
#include<vector>
#include<string>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
struct node {
int xmin, ymin, xmax, ymax;
node() :xmin(31), ymin(31), xmax(0), ymax(0) {}//构造函数
};
char ans[30];
bool v[30][30];//为了防止对同一个边多次记录,就用邻接矩阵来记录边
int ind[30];
map<char, node> save;
int n, m;
char pic[31][31];
void init()
{
memset(ind, 0, sizeof(ind));
memset(v, false, sizeof(v));
save.clear();
}
void print(int len)
{
for (int i = 0; i < len; i++)
printf("%c", ans[i]);
printf("\n");
}
void topo(int len)
{
if (len == save.size())
return print(len);
int j, k;
for (j = 0; j < 26; j++)
{
if (save.count(j + 'A') && ind[j] == 0)
{
ans[len] = j + 'A';
ind[j] = -1;
for (k = 0; k < 26; k++)
{
if (v[j][k])
ind[k]--;
}
topo(len + 1);
ind[j] = 0;
for (k = 0; k < 26; k++)
{
if (v[j][k])
ind[k]++;
}
}
}
}
void build()
{
int i, j;
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
if (pic[i][j] == '.')
continue;
char now = pic[i][j];
if (!save.count(now))
save[now] = node();
save[now].xmax = max(save[now].xmax, i);//更新左上角与右下角的坐标
save[now].ymax = max(save[now].ymax, j);
save[now].xmin = min(save[now].xmin, i);
save[now].ymin = min(save[now].ymin, j);
}
}
for (map<char, node>::iterator it = save.begin(); it != save.end(); ++it)
{
//分别扫描矩形的四个边,如果有其他字母覆盖就建立有向边
char ch = it->first;
int x1 = it->second.xmin, y1 = it->second.ymin, x2 = it->second.xmax, y2 = it->second.ymax;
for (i = x1; i <= x2; i++) if (pic[i][y1] != ch&&!v[ch - 'A'][pic[i][y1] - 'A'])
{
v[ch - 'A'][pic[i][y1] - 'A'] = true;
ind[pic[i][y1] - 'A']++;
}//y1
for (i = x1; i <= x2; i++) if (pic[i][y2] != ch&&!v[ch - 'A'][pic[i][y2] - 'A'])
{
v[ch - 'A'][pic[i][y2] - 'A'] = true;
ind[pic[i][y2] - 'A']++;
}//y2
for (i = y1; i <= y2; i++) if (pic[x1][i] != ch&&!v[ch - 'A'][pic[x1][i] - 'A'])
{
v[ch - 'A'][pic[x1][i] - 'A'] = true;
ind[pic[x1][i] - 'A']++;
}//x1
for (i = y1; i <= y2; i++) if (pic[x2][i] != ch&&!v[ch - 'A'][pic[x2][i] - 'A'])
{
v[ch - 'A'][pic[x2][i] - 'A'] = true;
ind[pic[x2][i] - 'A']++;
}//x2
}
}
int main()
{
// freopen("D://input.txt", "r", stdin);
// freopen("D://output.txt", "w", stdout);
while (scanf("%d", &n) != EOF)
{
scanf("%d", &m);
int i;
for (i = 0; i < n; i++)
scanf("%s", pic[i]);
init();
build();
topo(0);
}
// printf("%.6lf\n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}