首页 > 编程语言 > 详细

USACO4.4 Frame Up【拓扑排序】

时间:2019-11-13 09:30:54      阅读:104      评论:0      收藏:0      [点我收藏+]

题意居然还读了好久...

读完题目之后大概就知道拓扑排序了。用拓扑可以求出一些字母之间的关系,谁先,谁后。但是这个关系不是唯一确定的,所以就会产生多种方案(题目还要求按字典序输出所有的方案)

输出方案要麻烦一些,最刚开始还没有想到。可以用一个$dfs$,当这个点的入度变为$0$之后,就输出,递归到下一层,然后再回溯。按字母的字典序枚举就可以输出按字典序排的方案。

技术分享图片
  1 /*
  2 ID: Starry21
  3 LANG: C++
  4 TASK: frameup         
  5 */
  6 #include<cstdio>
  7 #include<algorithm>
  8 #include<vector>
  9 #include<cstring>
 10 #include<queue>
 11 #include<map>
 12 #include<iostream>
 13 using namespace std;
 14 #define ll long long
 15 #define INF 0x3f3f3f3f
 16 #define N 35
 17 int h,w,n/*一共n个图像(字母)*/;
 18 char mp[N][N];//存图 
 19 int s[N],x[N],z[N],y[N];//每个字母边框的上下左右边在哪一行(列) 
 20 char kd[N];//存字母(1~n) 
 21 bool vis[N];//各种标记 看地方 
 22 
 23 vector<int>G[N];//拓扑的边 
 24 int ind[N];//入度 
 25 char ans[N];
 26 void dfs(int k)
 27 {
 28     //printf("%d\n",k);
 29     if(k>n)
 30     {
 31         for(int i=1;i<=n;i++)
 32             printf("%c",ans[i]);
 33         puts("");
 34         return ;
 35     }
 36     for(int i=1;i<=n;i++)
 37         if(ind[kd[i]-A]==0&&!vis[i])
 38         {
 39             vis[i]=1;
 40             ans[k]=kd[i];
 41             for(int j=0;j<G[kd[i]-A].size();j++)
 42             {
 43                 int v=G[kd[i]-A][j];
 44                 ind[v]--;
 45             }
 46             dfs(k+1);
 47             vis[i]=0;
 48             for(int j=0;j<G[kd[i]-A].size();j++)
 49             {
 50                 int v=G[kd[i]-A][j];
 51                 ind[v]++;
 52             }
 53         }
 54 }
 55 int main() 
 56 {
 57     //freopen("frameup.in","r",stdin);
 58     //freopen("frameup.out","w",stdout);
 59     scanf("%d %d",&h,&w);
 60     for(int i=1;i<=h;i++)
 61     {
 62         scanf("%s",mp[i]+1);
 63         for(int j=1;j<=w;j++)
 64         {
 65             if(mp[i][j]==.) continue;
 66             if(!vis[mp[i][j]-A])
 67             {
 68                 kd[++n]=mp[i][j];
 69                 vis[mp[i][j]-A]=1;
 70             }
 71             if(!s[mp[i][j]-A]) s[mp[i][j]-A]=i;
 72             if(!z[mp[i][j]-A]) z[mp[i][j]-A]=j;
 73             if(!x[mp[i][j]-A]) x[mp[i][j]-A]=i;
 74             if(!y[mp[i][j]-A]) y[mp[i][j]-A]=j;
 75             s[mp[i][j]-A]=min(s[mp[i][j]-A],i);
 76             z[mp[i][j]-A]=min(z[mp[i][j]-A],j);
 77             x[mp[i][j]-A]=max(x[mp[i][j]-A],i);
 78             y[mp[i][j]-A]=max(y[mp[i][j]-A],j);
 79             /*
 80             题目保证方块的每一条边都有露出来的
 81             所以直接取min/max就好 
 82             */
 83         }
 84     }
 85     /*for(int i=1;i<=n;i++)
 86     {
 87         printf("%c\n",kd[i]);
 88         int id=kd[i]-‘A‘;
 89         printf("%d %d %d %d\n",s[id],x[id],z[id],y[id]);
 90     }*/
 91     memset(ind,-1,sizeof(ind));//排除无关字母 
 92     for(int i=1;i<=n;i++)
 93         ind[kd[i]-A]=0;
 94     for(int i=1;i<=n;i++)//枚举字母
 95     {
 96         memset(vis,0,sizeof(vis));//清空 标记这个点连了哪些 不连重边 
 97         int id=kd[i]-A;
 98         for(int j=z[id];j<=y[id];j++)
 99             if(mp[s[id]][j]!=kd[i]&&!vis[mp[s[id]][j]-A])
100             {
101                 G[id].push_back(mp[s[id]][j]-A);
102                 vis[mp[s[id]][j]-A]=1;
103                 ind[mp[s[id]][j]-A]++;
104             }
105         for(int j=z[id];j<=y[id];j++)
106             if(mp[x[id]][j]!=kd[i]&&!vis[mp[x[id]][j]-A])
107             {
108                 G[id].push_back(mp[x[id]][j]-A);
109                 vis[mp[x[id]][j]-A]=1;
110                 ind[mp[x[id]][j]-A]++;
111             }
112         for(int j=s[id];j<=x[id];j++)
113             if(mp[j][z[id]]!=kd[i]&&!vis[mp[j][z[id]]-A])
114             {
115                 G[id].push_back(mp[j][z[id]]-A);
116                 vis[mp[j][z[id]]-A]=1;
117                 ind[mp[j][z[id]]-A]++;
118             }
119         for(int j=s[id];j<=x[id];j++)
120             if(mp[j][y[id]]!=kd[i]&&!vis[mp[j][y[id]]-A])
121             {
122                 G[id].push_back(mp[j][y[id]]-A);
123                 vis[mp[j][y[id]]-A]=1;
124                 ind[mp[j][y[id]]-A]++;
125             }
126     }
127     sort(kd+1,kd+n+1);
128     memset(vis,0,sizeof(vis));
129     dfs(1);//按照拓扑排序 入度为0之后可以选也可以不选 题目保证有解 
130     return 0;
131 }
Code

 

 

USACO4.4 Frame Up【拓扑排序】

原文:https://www.cnblogs.com/lyttt/p/11846554.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!