1.记录每个出现的不同的字母的边界
2.记录这个字母是否在原图中出现
3.入度记录该字母是否覆盖了其他字母
4.拓扑排序
5.深搜时的递归记得回溯
代码在这:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <iterator>
#include <vector>
using namespace std;
struct node
{
int x1,x2;
int y1,y2;
node()
{
x1=y1=100;
x2=y2=-100;
}
};
bool used[30];
int into[30];
char s[50][50];
int p[50][50];
vector<char> ans;
void build(node f[])
{
for(int i=0;i<26;++i)
{
if(used[i])
{
for(int j=f[i].x1;j<=f[i].x2;++j)
{
if(s[j][f[i].y1]!=i+'A'){
int z=s[j][f[i].y1]-'A';
if(p[i][z]==0)
{
into[z]++;
p[i][z]=1;
}
}
if(s[j][f[i].y2]!=i+'A'){
int z=s[j][f[i].y2]-'A';
if(p[i][z]==0)
{
into[z]++;
p[i][z]=1;
}
}
}
for(int j=f[i].y1;j<=f[i].y2;++j)
{
if(s[f[i].x1][j]!=i+'A'){
int z=s[f[i].x1][j]-'A';
if(p[i][z]==0)
{
into[z]++;
p[i][z]=1;
}
}
if(s[f[i].x2][j]!=i+'A'){
int z=s[f[i].x2][j]-'A';
if(p[i][z]==0)
{
into[z]++;
p[i][z]=1;
}
}
}
}
}
}
void po(int dep,int cnt)
{
if(dep>=cnt)
{
copy(ans.begin(),ans.end(),ostream_iterator<char>(cout));
cout<<endl;
return;
}
for(int i=0;i<26;++i)
{
if(used[i]){
if(into[i]==0)
{
ans.push_back(i+'A');
into[i]=-1;
for(int k=0;k<26;++k)
if(p[i][k]==1) into[k]--;
po(dep+1,cnt);
ans.pop_back();
into[i]=0;
for(int k=0;k<26;++k)
if(p[i][k]==1) into[k]++;
}
}
}
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(p,0,sizeof(p));
memset(s,0,sizeof(s));
memset(used,0,sizeof(used));
memset(into,0,sizeof(into));
node f[30];
ans.clear();
char ss[50];
getchar();
for(int i=0;i<n;++i)
{
scanf("%s",ss);
for(int j=0;j<m;++j)
{
s[i][j]=ss[j];
if(s[i][j]!='.')
{
int w=s[i][j]-'A';
used[w]=true;
if(i<f[w].x1) f[w].x1=i;
if(i>f[w].x2) f[w].x2=i;
if(j<f[w].y1) f[w].y1=j;
if(j>f[w].y2) f[w].y2=j;
}
}
}
build(f);
int cnt=0;
for(int i=0;i<26;++i)
if(used[i]) cnt++;
po(0,cnt);
}
return 0;
}