zoukankan      html  css  js  c++  java
  • USACO4.4 Frame Up【拓扑排序】

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

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

    输出方案要麻烦一些,最刚开始还没有想到。可以用一个$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
    ",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
    ",kd[i]);
     88         int id=kd[i]-'A';
     89         printf("%d %d %d %d
    ",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
  • 相关阅读:
    iOS URL中汉字的编码和解码
    指针函数和函数指针
    面试题1:赋值运算符函数
    线程安全的单实例模式
    大数相加
    网格走法
    stringstream字符串流的妙用
    判断一棵二叉树是否为二叉排序树
    idea 从javadoc中复制内容出来
    idea开启jquery提示及如何找到学习目标
  • 原文地址:https://www.cnblogs.com/lyttt/p/11846554.html
Copyright © 2011-2022 走看看