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

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

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

 /*
ID: Starry21
LANG: C++
TASK: frameup
*/
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define N 35
int h,w,n/*一共n个图像(字母)*/;
char mp[N][N];//存图
int s[N],x[N],z[N],y[N];//每个字母边框的上下左右边在哪一行(列)
char kd[N];//存字母(1~n)
bool vis[N];//各种标记 看地方 vector<int>G[N];//拓扑的边
int ind[N];//入度
char ans[N];
void dfs(int k)
{
//printf("%d\n",k);
if(k>n)
{
for(int i=;i<=n;i++)
printf("%c",ans[i]);
puts("");
return ;
}
for(int i=;i<=n;i++)
if(ind[kd[i]-'A']==&&!vis[i])
{
vis[i]=;
ans[k]=kd[i];
for(int j=;j<G[kd[i]-'A'].size();j++)
{
int v=G[kd[i]-'A'][j];
ind[v]--;
}
dfs(k+);
vis[i]=;
for(int j=;j<G[kd[i]-'A'].size();j++)
{
int v=G[kd[i]-'A'][j];
ind[v]++;
}
}
}
int main()
{
//freopen("frameup.in","r",stdin);
//freopen("frameup.out","w",stdout);
scanf("%d %d",&h,&w);
for(int i=;i<=h;i++)
{
scanf("%s",mp[i]+);
for(int j=;j<=w;j++)
{
if(mp[i][j]=='.') continue;
if(!vis[mp[i][j]-'A'])
{
kd[++n]=mp[i][j];
vis[mp[i][j]-'A']=;
}
if(!s[mp[i][j]-'A']) s[mp[i][j]-'A']=i;
if(!z[mp[i][j]-'A']) z[mp[i][j]-'A']=j;
if(!x[mp[i][j]-'A']) x[mp[i][j]-'A']=i;
if(!y[mp[i][j]-'A']) y[mp[i][j]-'A']=j;
s[mp[i][j]-'A']=min(s[mp[i][j]-'A'],i);
z[mp[i][j]-'A']=min(z[mp[i][j]-'A'],j);
x[mp[i][j]-'A']=max(x[mp[i][j]-'A'],i);
y[mp[i][j]-'A']=max(y[mp[i][j]-'A'],j);
/*
题目保证方块的每一条边都有露出来的
所以直接取min/max就好
*/
}
}
/*for(int i=1;i<=n;i++)
{
printf("%c\n",kd[i]);
int id=kd[i]-'A';
printf("%d %d %d %d\n",s[id],x[id],z[id],y[id]);
}*/
memset(ind,-,sizeof(ind));//排除无关字母
for(int i=;i<=n;i++)
ind[kd[i]-'A']=;
for(int i=;i<=n;i++)//枚举字母
{
memset(vis,,sizeof(vis));//清空 标记这个点连了哪些 不连重边
int id=kd[i]-'A';
for(int j=z[id];j<=y[id];j++)
if(mp[s[id]][j]!=kd[i]&&!vis[mp[s[id]][j]-'A'])
{
G[id].push_back(mp[s[id]][j]-'A');
vis[mp[s[id]][j]-'A']=;
ind[mp[s[id]][j]-'A']++;
}
for(int j=z[id];j<=y[id];j++)
if(mp[x[id]][j]!=kd[i]&&!vis[mp[x[id]][j]-'A'])
{
G[id].push_back(mp[x[id]][j]-'A');
vis[mp[x[id]][j]-'A']=;
ind[mp[x[id]][j]-'A']++;
}
for(int j=s[id];j<=x[id];j++)
if(mp[j][z[id]]!=kd[i]&&!vis[mp[j][z[id]]-'A'])
{
G[id].push_back(mp[j][z[id]]-'A');
vis[mp[j][z[id]]-'A']=;
ind[mp[j][z[id]]-'A']++;
}
for(int j=s[id];j<=x[id];j++)
if(mp[j][y[id]]!=kd[i]&&!vis[mp[j][y[id]]-'A'])
{
G[id].push_back(mp[j][y[id]]-'A');
vis[mp[j][y[id]]-'A']=;
ind[mp[j][y[id]]-'A']++;
}
}
sort(kd+,kd+n+);
memset(vis,,sizeof(vis));
dfs();//按照拓扑排序 入度为0之后可以选也可以不选 题目保证有解
return ;
}

Code

USACO4.4 Frame Up【拓扑排序】的更多相关文章

  1. POJ 1128 Frame Stacking (拓扑排序)

    题目链接 Description Consider the following 5 picture frames placed on an 9 x 8 array. ........ ........ ...

  2. Frame Stacking 拓扑排序 图论

    Description Consider the following 5 picture frames placed on an 9 x 8 array. ........ ........ .... ...

  3. POJ 1128 Frame Stacking 拓扑排序+暴搜

    这道题输出特别坑.... 题目的意思也不太好理解.. 就解释一下输出吧.. 它让你 从下往上输出. 如果有多种情况,按照字典序从小往大输出... 就是这个多种情况是怎么产生的呢. 下面给一组样例. 很 ...

  4. Frame Stacking(拓扑排序)

    题目链接:http://acm.tju.edu.cn/toj/showp1076.html1076.   Frame Stacking Time Limit: 1.0 Seconds   Memory ...

  5. POJ1128 Frame Stacking(拓扑排序+dfs)题解

    Description Consider the following 5 picture frames placed on an 9 x 8 array.  ........ ........ ... ...

  6. POJ 1128 Frame Stacking(拓扑排序&#183;打印字典序)

    题意  给你一些矩形框堆叠后的鸟瞰图  推断这些矩形框的堆叠顺序  每一个矩形框满足每边都至少有一个点可见  输入保证至少有一个解 按字典序输出全部可行解 和上一题有点像  仅仅是这个要打印全部的可行 ...

  7. POJ1128 Frame Stacking(拓扑排序)

    题目链接:http://poj.org/problem?id=1128 题意:给你一个平面,里面有些矩形(由字母围成),这些矩形互相有覆盖关系,请从求出最底层的矩形到最上层的矩形的序列,如果存在多种序 ...

  8. 图论之拓扑排序 poj1128 Frame Stacking

    题目网址 http://poj.org/problem?id=1128 思路:遍历找出每一种字母出现的最大和最小的横纵坐标,假如本应出现字母A的地方出现了字母B,那么A一定在字母B之前,这就相当于点A ...

  9. ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083)-POJ1270)

    两道经典的同类型拓扑排序+DFS问题,第二题较第一题简单,其中的难点在于字典序输出+建立单向无环图,另外理解题意是最难的难点,没有之一... POJ1128(ZOJ1083)-Frame Stacki ...

随机推荐

  1. php类相关知识---__unset和__isset

    __unset 删除非公有属性,在外部调用unset时发生,  __isset用来检测对象属性是否设置值 <?php class coach { protected $chairfit = &q ...

  2. python中ord()函数,chr()函数,unichr()函数

    ord()函数,chr()函数,unichr()函数 chr()函数用一个范围在range(256)内的(就是0-255)整数作参数,返回一个对应的字符.unichr()跟它一样,只不过返回的是Uni ...

  3. Java之正则表达式来判断字符串中是否包含字母

    /** * 使用正则表达式来判断字符串中是否包含字母 * @param str 待检验的字符串 * @return 返回是否包含 * true: 包含字母 ;false 不包含字母 */ public ...

  4. Machine Learning(Andrew Ng)学习笔记

    1.监督学习(supervised learning)&非监督学习(unsupervised learning) 监督学习:处理具有若干属性且返回值不同的对象.分为回归型和分类型:回归型的返回 ...

  5. hdu 6068 Classic Quotation

    题 QAQ http://acm.hdu.edu.cn/showproblem.php?pid=6068 2017 Multi-University Training Contest - Team 4 ...

  6. word文档在线预览地址

    文档网址 http://www.officeweb365.com/Default/Docview 对接 http://ow365.cn/?i=19604&furl=http:://www.ba ...

  7. C#验证数字的正则表达

    说明:@符号的作用,省去转义字符\ "^\\+?[1-9][0-9]*$" 与 @"^\+?[1-9][0-9]*$"   等效 @"^(0?[1-9 ...

  8. SQL中where in的用法

    首先我们要知道where是什么:一个判断符.在SQL操作中,控制只选择指定的行. in的其实归类于特殊的比较运算符 expr1 between expr2 and expr3:表示expr1的值在ex ...

  9. java批量下载

    最近做了一些有关批量压缩下载的功能,网上也找了一些资源,但都不是太全面,所以自己整理一份,已备不时之需. 直接上代码: // 获取项目路径     private static String WEBC ...

  10. The 2018 ACM-ICPC Asia Qingdao Regional Contest, Online(2018 青岛网络预选赛)

    A题 A Live Love 原题链接:https://pintia.cn/problem-sets/1036903825309761536/problems/1041155943483625472 ...