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 }

 

posted @ 2015-03-25 16:49  Naturain  阅读(229)  评论(0编辑  收藏  举报