传送门: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; }