Frame Stacking

poj1128:http://poj.org/problem?id=1128

题意:一个二维图里面有几个相框(四条边的空心矩形框)。有重叠,求重叠顺序。还有题目保证至少存在一种符合要求的序列,当有多种情况时按字典序由小到大输出所有的情况。

题解:建图然后+topsort+dfs ,建图很麻烦的,要细心处理。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #include <iterator>//stl迭代器 
  7 using namespace std;
  8 char map[32][32];//记录原图 
  9 int g[27][27];//topsort的图 
 10 int counts[27];//记录入度 
 11 int n,m,num;// 行和列 以及出现过的字母的个数 
 12 bool visit[27];//记录出现过的字母 
 13 vector<char> ans;//记录结果 
 14 struct Node{
 15     int x1,y1;
 16     int x2,y2;
 17 }edge[27];//储存每个节点出现的最左,最右,最上,最下的坐标。 
 18 void init(){
 19     num=0;//初始化 
 20     memset(g,0,sizeof(g));
 21     memset(map,0,sizeof(map));
 22     for(int i=1;i<=26;i++){  
 23         counts[i]=0;
 24           visit[i]=false;
 25           edge[i].x1=edge[i].y1=100;
 26           edge[i].x2=edge[i].y2=-100;
 27          }
 28 }
 29 void build1(){//建图 
 30     for(int i=1;i<=n;i++)
 31       for(int j=1;j<=m;j++){
 32          cin>>map[i][j];
 33         if(map[i][j]!='.'){
 34          if(!visit[map[i][j]-'A'+1]){
 35               num++;
 36               visit[map[i][j]-'A'+1]=true;
 37           }//统计出现过的字母 
 38         if(edge[map[i][j]-'A'+1].x1>i){
 39             edge[map[i][j]-'A'+1].x1=i;
 40         }
 41         if(edge[map[i][j]-'A'+1].y1>j){
 42             edge[map[i][j]-'A'+1].y1=j;
 43         }
 44         if(edge[map[i][j]-'A'+1].x2<i){
 45             edge[map[i][j]-'A'+1].x2=i;
 46         }
 47         if(edge[map[i][j]-'A'+1].y2<j){
 48             edge[map[i][j]-'A'+1].y2=j;
 49         }//不断更新各个图片的上下左右的值 
 50         
 51     }
 52   }
 53 }
 54 void build2(){//开始建topsort的图g 
 55     for(int i=1;i<=26;i++){
 56         if(visit[i]){//如果出现过 
 57         for(int j=edge[i].y1;j<=edge[i].y2;j++){//遍历第一行(最上面的一行)找出与该图不同的图,如果不同 
 58             if(map[edge[i].x1][j]!=i+'A'-1&&!g[i][map[edge[i].x1][j]-'A'+1]){
 59                 g[i][map[edge[i].x1][j]-'A'+1]=1;//如果没有建边,而且满足覆盖关系 
 60                 counts[map[edge[i].x1][j]-'A'+1]++;
 61             }
 62         }
 63         for(int j=edge[i].y1;j<=edge[i].y2;j++){//最下面的一行 
 64             if(map[edge[i].x2][j]!=i+'A'-1&&!g[i][map[edge[i].x2][j]-'A'+1]){
 65                 g[i][map[edge[i].x2][j]-'A'+1]=1;
 66                 counts[map[edge[i].x2][j]-'A'+1]++;
 67             }
 68         }
 69         for(int j=edge[i].x1;j<=edge[i].x2;j++){//最左边的一列 
 70             if(map[j][edge[i].y1]!=i+'A'-1&&!g[i][map[j][edge[i].y1    ]-'A'+1]){
 71                 g[i][map[j][edge[i].y1]-'A'+1]=1;
 72                 counts[map[j][edge[i].y1]-'A'+1]++;
 73             }
 74         }
 75         for(int j=edge[i].x1;j<=edge[i].x2;j++){//最右边的一列 
 76             if(map[j][edge[i].y2]!=i+'A'-1&&!g[i][map[j][edge[i].y2]-'A'+1]){
 77                 g[i][map[j][edge[i].y2]-'A'+1]=1;
 78                 counts[map[j][edge[i].y2]-'A'+1]++;
 79             }
 80         }
 81     }
 82   }
 83 }
 84 void topo(int depth, int count){//排序,depth记录已经处理的字符的个数,count为总的字符个数 
 85     
 86    if (depth >= count){//达到开始值就开始输出 
 87     copy(ans.begin(), ans.end(), ostream_iterator<char>(cout));
 88        cout << endl;
 89        return;
 90     }//
 91    for (int i = 1; i <=26; ++i){
 92       if(visit[i]){
 93            if (counts[i] == 0){
 94             ans.push_back(i+'A'-1);
 95             counts[i] = -1;
 96    for (int k = 1; k <=26; ++k){
 97       if (g[i][k] == 1){
 98             counts[k]--;
 99       }
100    }
101    //递归向下 
102       topo(depth+1, count); 
103       ans.pop_back();//恢复现场1是ans里面的值要删除,2是各个点的入度要恢复+1; 
104       counts[i] = 0;
105    for (int k = 1; k <=26; ++k){
106       if (g[i][k] == 1){
107         counts[k]++;
108         }
109    }
110          }
111         }
112     }
113 }
114 int main(){
115     while(~scanf("%d%d",&n,&m)){
116         init();
117         ans.clear();//清除 
118         build1();
119         build2();
120         topo(0,num);//从0开始 
121     }
122 }
View Code
原文地址:https://www.cnblogs.com/chujian123/p/3361949.html