USACO 4.4 Frame Up(拓扑排序,全部解)
2015-03-25 16:21:58
思路:题意是给出若干(<=26)个矩形框,而且这个框只有最外面的一圈,根据将他们堆叠后的俯视图像来推断这些框的堆叠方式。字典序输出所有可能。
首先,题目保证根据俯视图你能确定每个矩形框的边长,那么我们开up,down,left,right四个数组来记录每个字母的最上/下/左/右的坐标,这样就可以确定矩形框的方位了。
考虑用拓扑排序来做,那么如何建边呢?
(1)扫描每个矩形框(设当前框为字母 i ),发现不同于 i 的字母 j ,那么说明 j 的框在 i 框上面,那么建边 j -> i。(表示把 j 框拿掉才能拿 i 框)
所以,入度为0的字母框就是最上面的框,那么我们只要把拓扑排序看做一个不断“拿”框的过程即可。
(2)由于题目要求求出所有解,那么考虑用DFS实现拓扑序,对每个入度为0的字母,DFS进去,并且在DFS过程中维护一个vector来存储解。
当然,在遍历一个点之前将其删除,并根据其出边减掉相应点的入度。在回溯回来时要恢复遍历前的状态。
(3)当发现已经遍历完所有点时要保存解,最后对解排序再输出。
1 /* 2 ID:naturec1 3 PROG: frameup 4 LANG: C++ 5 */ 6 #include <cstdio> 7 #include <cstring> 8 #include <cstdlib> 9 #include <cmath> 10 #include <vector> 11 #include <map> 12 #include <set> 13 #include <stack> 14 #include <queue> 15 #include <string> 16 #include <iostream> 17 #include <algorithm> 18 using namespace std; 19 20 #define MEM(a,b) memset(a,b,sizeof(a)) 21 #define REP(i,n) for(int i=0;i<(n);++i) 22 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 23 #define getmid(l,r) ((l) + ((r) - (l)) / 2) 24 #define MP(a,b) make_pair(a,b) 25 26 typedef long long ll; 27 typedef pair<int,int> pii; 28 const int INF = (1 << 30) - 1; 29 30 char g[50][50]; 31 int W,H,tot; 32 int id[30]; 33 int Up[30],Down[30],Left[30],Right[30]; 34 int mx[30][30]; 35 int deg[30],st_deg[30]; 36 vector<vector<int> > ans; 37 vector<int> now_ans; 38 39 void Add_edge(int p){ 40 int cur; 41 for(int j = Left[p]; j <= Right[p]; ++j){ 42 cur = g[Up[p]][j] - 'A'; 43 if(cur != p) mx[cur][p] = 1; 44 cur = g[Down[p]][j] - 'A'; 45 if(cur != p) mx[cur][p] = 1; 46 } 47 for(int i = Up[p]; i <= Down[p]; ++i){ 48 cur = g[i][Left[p]] - 'A'; 49 if(cur != p) mx[cur][p] = 1; 50 cur = g[i][Right[p]] - 'A'; 51 if(cur != p) mx[cur][p] = 1; 52 } 53 } 54 55 void Dfs(int p,int num){ 56 if(num >= tot){ 57 vector<int> tmp; 58 for(int i = now_ans.size() - 1; i >= 0; --i) 59 tmp.push_back(now_ans[i]); 60 ans.push_back(tmp); 61 return; 62 } 63 REP(i,26) if(id[i]){ 64 if(deg[i] == 0){ 65 now_ans.push_back(i); 66 deg[i] = -1; 67 REP(j,26) if(mx[i][j]) deg[j]--; 68 // 69 Dfs(i,num + 1); 70 // 71 now_ans.pop_back(); 72 deg[i] = 0; 73 REP(j,26) if(mx[i][j]) deg[j]++; 74 } 75 } 76 } 77 78 int main(){ 79 freopen("frameup.in","r",stdin); 80 freopen("frameup.out","w",stdout); 81 MEM(mx,0); 82 MEM(id,0); 83 scanf("%d%d",&H,&W); 84 REP(i,H) scanf("%s",g[i]); 85 REP(i,H) REP(j,W) if(g[i][j] != '.'){ 86 int cur = g[i][j] - 'A'; 87 if(id[cur] == 0){ 88 id[cur] = 1; 89 ++tot; 90 Up[cur] = Down[cur] = i; 91 Left[cur] = Right[cur] = j; 92 } 93 else{ 94 Up[cur] = min(Up[cur],i); 95 Down[cur] = max(Down[cur],i); 96 Left[cur] = min(Left[cur],j); 97 Right[cur] = max(Right[cur],j); 98 } 99 } 100 REP(i,26) if(id[i]) Add_edge(i); 101 REP(i,26) REP(j,26) if(mx[i][j]) st_deg[j]++; 102 REP(i,26) if(id[i] && st_deg[i] == 0){ 103 memcpy(deg,st_deg,sizeof(st_deg)); 104 now_ans.clear(); 105 now_ans.push_back(i); 106 deg[i] = -1; 107 REP(j,26) if(mx[i][j]) deg[j]--; 108 Dfs(i,1); 109 } 110 sort(ans.begin(),ans.end()); 111 REP(i,ans.size()){ 112 REP(j,tot) printf("%c",ans[i][j] + 'A'); 113 puts(""); 114 } 115 return 0; 116 }