链接:https://vjudge.net/problem/POJ-1128
题意:
每张图片上面画了一些边框,给出这些边框叠在一起后的图片,图片边框一定是由一个字母表示并且每条边至少三个字符,输入保证至少会给出边框每条边的一个字母,一个角的一个字符表示两条边,图片边框用大写字母表示,并且不会有两张图片的边框使用同一个大写字母,求从下往上的重叠顺序,如果有多种结果的话就按照字典序输出所有结果
思路:
先建图,找每个图内部的图片个数,同时记录。
因为不用种类的都要输出,按照从小到大的字典序去DFS。
代码:
#include <iostream>
#include <memory.h>
#include <vector>
#include <map>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <queue>
#include <string>
#include <stack>
#include <iterator>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
using namespace std;
typedef long long LL;
const int MAXN = 30 + 10;
char G[MAXN][MAXN];
char res[MAXN];
int M[MAXN][MAXN];
int Vis[MAXN];
int in[MAXN];
int n, m, cnt;
void Init()
{
cnt = 0;
memset(Vis, 0, sizeof(Vis));
memset(in, 0, sizeof(in));
memset(M, 0, sizeof(M));
}
void DFS(int num)
{
if (num == cnt)
{
res[num] = '\0';
cout << res << endl;
return;
}
for (int i = 0;i < 26;i++)
{
if (in[i] == 0 && Vis[i])
{
res[num] = 'A'+i;
in[i] = -1;
for (int j = 0;j < 26;j++)
if (M[i][j])
--in[j];
DFS(num+1);
in[i] = 0;
for (int j = 0;j < 26;j++)
if (M[i][j])
++in[j];
}
}
return;
}
int main()
{
while (cin >> n >> m)
{
Init();
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
cin >> G[i][j];
for (int k = 0;k < 26;k++)
{
int x1 = MAXN, y1 = MAXN, x2 = -1, y2 = -1;
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
{
if (G[i][j] == 'A'+k)
{
x1 = min(x1, i);
y1 = min(y1, j);
x2 = max(x2, i);
y2 = max(y2, j);
}
}
if (x1 == MAXN || y1 == MAXN || x2 == -1 || y2 == -1)
continue;
Vis[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 (G[i][j] != 'A'+k && G[i][j] != '.')
{
int t = G[i][j]-'A';
if (!M[k][t])
++in[t], M[k][t] = 1;
}
}
}
}
}
DFS(0);
}
return 0;
}