Solution
今天上午测试题...最后几分钟才看到要输出所有解,于是爆成了 44pts...
根据输入可以得到所有字母构成的矩形。如果字符 (i) 出现在了字符 (j) 的矩形上,那么 (i) 的图像一定在 (j) 的图像上方,从 (j) 向 (i) 连边。
跑一个拓扑排序,每次可以选的是队列里所有点之一。因此需要 dfs 所有可能情况,最后存到变量里按照字典序输出。
手写队列要注意,不能直接对队列排序,dfs 时会造成混乱。
Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2333;
char a[N][N];
int n, m, Num = 0, tot = 0, res = 0;
int vis[N], lx[N], rx[N], ly[N], ry[N], e[N][N];
int q[N], du[N], use[N];
string ans[2333333];
void dfs(int num, int stp)
{
if(stp == Num)
{
res++;
ans[res] = "";
for(int i = 1; i <= stp; i++) ans[res] += (char)(use[i]);
return ;
}
for(int i = 1; i <= num; i++)
{
int x = q[i], cnt = num - 1;
for(int j = i; j < num; j++) q[j] = q[j + 1];
for(int j = 'A'; j <= 'Z'; j++)
{
if(vis[j] && e[x][j])
{
du[j]--;
if(du[j] == 0) q[++cnt] = j;
}
}
use[stp + 1] = x;
dfs(cnt, stp + 1);
for(int j = num; j > i; j--) q[j] = q[j - 1];
q[i] = x;
for(int j = 'A'; j <= 'Z'; j++)
if(vis[j] && e[x][j]) du[j]++;
}
}
int main()
{
scanf("%d%d", &n, &m);
memset(e, 0, sizeof(e));
memset(lx, 0x3f, sizeof(lx));
memset(ly, 0x3f, sizeof(ly));
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
cin >> a[i][j];
if(a[i][j] >= 'A' && a[i][j] <= 'Z')
{
if(!vis[a[i][j]])
{
vis[a[i][j]] = 1;
Num++;
}
lx[a[i][j]] = min(lx[a[i][j]], i);
ly[a[i][j]] = min(ly[a[i][j]], j);
rx[a[i][j]] = max(rx[a[i][j]], i);
ry[a[i][j]] = max(ry[a[i][j]], j);
}
}
for(int i = 'A'; i <= 'Z'; i++)
{
if(!vis[i]) continue;
for(int j = ly[i]; j <= ry[i]; j++)
{
char ch1 = a[lx[i]][j], ch2 = a[rx[i]][j];
if(vis[ch1] && ch1 != i) e[i][ch1] = 1;
if(vis[ch2] && ch2 != i) e[i][ch2] = 1;
}
for(int j = lx[i]; j <= rx[i]; j++)
{
char ch1 = a[j][ly[i]], ch2 = a[j][ry[i]];
if(vis[ch1] && ch1 != i) e[i][ch1] = 1;
if(vis[ch2] && ch2 != i) e[i][ch2] = 1;
}
}
memset(du, 0, sizeof(du));
for(int i = 'A'; i <= 'Z'; i++)
{
if(!vis[i]) continue;
for(int j = 'A'; j <= 'Z'; j++)
{
if(!vis[j]) continue;
if(e[i][j] == 1) du[j]++;
}
}
for(int i = 'A'; i <= 'Z'; i++)
{
if(!vis[i]) continue;
if(du[i] == 0)
{
tot++;
q[tot] = i;
}
}
dfs(tot, 0);
sort(ans + 1, ans + res + 1);
for(int i = 1; i <= res; i++) cout << ans[i] << endl;
return 0;
}