思考了很久这道题目
还是没想到该如何下手
看到了这位大佬的代码
http://www.cnblogs.com/Inkblots/p/5351764.html
迷迷糊糊看个大概
才明白原来对于每张图的边框可以这样获得
然后就是拓扑排序
对于多解的情况要用到回溯法
然而还是不是很熟练
还是WA
先贴上来。。
#include<iostream>
#include<string.h>
using namespace std;
struct Point
{
int x;
Point* next;
}p[26];
int map[30][30],num[26],out[26]; //均从0开始
int topx[26], topy[26], bottomx[26], bottomy[26]; //左上顶点,右下顶点,方便初始化
bool ix[26], v[26];
void init(int h, int w);
void add(int k, int i);
void print(int x);
int len;
int main()
{
int h, w, i, j,k,t;
while (cin >> h >> w)
{
init(h,w);
for (i = 0; i < 26; i++)
{
if (ix[i] == 1) //生成邻接表
{
memset(v, 0, sizeof(v));
len++;
t = topy[i];
for (j = topx[i]; j <= bottomx[i]; j++) //第一行
{
k = map[t][j];
add(k, i);
}
t = bottomy[i];
for (j = topx[i]; j <= bottomx[i]; j++)
{
k = map[t][j];
add(k, i);
}
t = topx[i]; //第一列
for (j = topy[i]; j <= bottomy[i]; j++)
{
k = map[j][t];
add(k, i);
}
t = bottomx[i];
for (j = topy[i]; j <= bottomy[i]; j++)
{
k = map[j][t];
add(k, i);
}
}
}
print(0);
}
return 0;
}
void init(int h, int w)
{
char read;
memset(topx, 1, sizeof(int)*26);
memset(topy, 1, sizeof(topy));
memset(bottomx, 0, sizeof(bottomx));
memset(bottomy, 0, sizeof(bottomy));
memset(ix, 0, sizeof(ix));
memset(num, 0, sizeof(num));
memset(out, 0, sizeof(out));
memset(map, 0, sizeof(map));
memset(p, 0, sizeof(p));
len = 0;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
cin >> read;
if (read != '.')
{
map[i][j] = read - 'A';
ix[map[i][j]] = 1;
if (topy[map[i][j]] > i)
topy[map[i][j]] = i;
if (topx[map[i][j]] > j)
topx[map[i][j]] = j;
if (bottomy[map[i][j]] < i)
bottomy[map[i][j]] = i;
if (bottomx[map[i][j]] < j)
bottomx[map[i][j]] = j;
}
else
map[i][j] = -1; //A->0,B->1...,'.'->-1
}
}
}
void add(int k,int i)
{
Point *q, *m;
if (k != i&&v[k] != 1)
{
v[k] = 1;
q = new Point();
q->x = i;
q->next = 0;
m = &p[k];
while (m->next != NULL)
{
m = m->next;
}
m->next = q;
num[i]++;
}
}
void print(int x)
{
Point *m;
if (x == len)
{
for (int i = len - 1; i >= 0; i--)
{
cout << char(out[i] + 'A');
}
cout << endl;
return;
}
for (int j = 0; j < 26; j++)
{
if (!ix[j]) continue;
if (num[j] == 0)
{
out[x] = j;
num[j]--;
m = p[j].next;
while (m != NULL)
{
num[m->x]--;
m = m->next;
}
print(x+1);
m = p[j].next;
while (m != NULL)
{
num[m->x]++;
m = m->next;
}
num[j]++;
}
}
}
终于AC了!!!
实在是太不容易
总感觉自己好像没有错误才是最大的错误
说是要按照字典的顺序输出
想着直接DFS出来的肯定没有问题
然而
他输出的时候,并不是按照拓扑排序的正确顺序来的
而是反着来的
于是我所设置的反向输出
就破坏了DFS自己的字典顺序
又去拜读了上面链接的文档
发现人家从一开始的拓扑排序就是反着来的
这样就没有问题的
实在是混乱的一个晚上啊。。
#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
struct Point
{
int x;
Point* next;
}p[26];
int map[30][30],num[26]; //均从0开始
int topx[26], topy[26], bottomx[26], bottomy[26]; //左上顶点,右下顶点,方便初始化
bool ix[26], v[26];//ix是否存在该点,v是否访问了该点
void init(int h, int w);
void add(int k, int i);
void print(int x);
int len;
char ans[26];
int main()
{
int h, w, i, j,k,t;
while (cin >> h >> w)
{
init(h,w);
for (i = 0; i < 26; i++)
{
if (ix[i] == 1) //生成邻接表
{
memset(v, 0, sizeof(v));
len++;
//四条边都走一遍
for (j = topx[i]; j <= bottomx[i]; j++)
{
t = topy[i];
k = map[t][j];
add(k, i);
t = bottomy[i];
k = map[t][j];
add(k, i);
}
for (j = topy[i]; j <= bottomy[i]; j++)
{
t = topx[i];
k = map[j][t];
add(k, i);
t = bottomx[i];
k = map[j][t];
add(k, i);
}
}
}
print(0);
}
return 0;
}
void init(int h, int w)
{
char read;
for (int ii = 0; ii < 26; ii++)
topx[ii] = w;
for (int ii = 0; ii < 26; ii++)
topy[ii] = h;
memset(bottomx, 0, sizeof(bottomx));
memset(bottomy, 0, sizeof(bottomy));
memset(ix, 0, sizeof(ix));
memset(num, 0, sizeof(num));
memset(map, 0, sizeof(map));
memset(p, 0, sizeof(p));
len = 0;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
cin >> read;
if (read != '.')
{
map[i][j] = read - 'A';
ix[map[i][j]] = 1;
topy[map[i][j]]=min(topy[map[i][j]], i);
topx[map[i][j]]=min(topx[map[i][j]], j);
bottomy[map[i][j]]=max(bottomy[map[i][j]], i);
bottomx[map[i][j]]=max(bottomx[map[i][j]] , j);
}
else
map[i][j] = -1; //A->0,B->1...,'.'->-1
}
}
}
void add(int k,int i) //k是在上面的,i是在下面的,但是因为输出的顺序是反的,因此在指向时,反着来
{
Point *q, *m;
if (k != i&&v[k] != 1)
{
v[k] = 1;
q = new Point();
q->x = k;
q->next = 0;
m = &p[i];
while (m->next != NULL)
{
m = m->next;
}
m->next = q;
num[k]++;
}
}
void print(int x)
{
Point *m;
if (x == len)
{
ans[x] = '\0';
for (int i = 0; i <len; i++)
{
cout << ans[i];
}
cout << endl;
return;
}
for (int j = 0; j < 26; j++)
{
if (!ix[j]) continue;
if (num[j] == 0)
{
ans[x] = j + 'A';
num[j]--;
m = p[j].next;
while (m != NULL)
{
num[m->x]--;
m = m->next;
}
print(x+1);
m = p[j].next;
while (m != NULL)
{
num[m->x]++;
m = m->next;
}
num[j]++;
}
}
}