uva 1572
来源:互联网 发布:知已知彼的意思是什么 编辑:程序博客网 时间:2024/05/16 17:42
原题
锻炼思维的题, 这种类似的题都需要把问题转化为图论模型, 然后判断是否有环路(验证是否为DAG, 有向无环图)
图中共有52种不同的标记, 也就是有52个顶点, 而且因为字母相同的顶点之间有一定的关系, 所以读入边的时候需要做一点小处理,
需要先把边的一端的字母转换符号之后再标记边
一开始有一个理解的误区, 以为这道题可以转化为无向图, 因为看上去似乎并没有方向的问题
但后来发现用无环图会在一种边界情况(如一个block有两个相同的vertex)产生误判
还有就是复习了一下拓扑排序, 目前接触到的有两种, 一个是依次找度为0的顶点输出, 比较直观的方法
第二则是DFS, 这个和第一种方法思路完全相反, 因为DFS完之后生成一棵DFS树,
把这棵DFS树从最底层的叶节点(也就相当于度为0) 开始依次向上层输出, 也就是逆序的层序遍历
这种方法, 在DFS的时候, 先把其所有子树都DFS完毕再输出当前结点即可实现.
这道题我就用的第二种方法, 比较方便用于找环, 遍历的时候如果遇到已经标记visited的结点则说明有环
不过一开始忽略了一点, 就是遍历完子结点回溯的时候记得要再把该点的visited标记为false, 否则后面显然就会错了, 检查这个错误还检查了好久..
AC代码如下:
#include <iostream>#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <list>
#include <cassert>
#include <iomanip>
using namespace std;
const int MAXN = 52; // 原坐标系
typedef long long LL;
/*
uva 1572
关键 : 1. 注意到可以转化为图论模型, 每个大写字母及其符号作为一个顶点,
每个block代表2条有向路(因为可以任意旋转和翻转) ,则问题转化为是否能够找到一条有向图的环
2. 【关键步骤】: 根据题意要求, 读入一个block时要进行转换, 如读入K+00P-00
则代表 Edge[K-][P-] = true 而非 Edge[K+][P-] = true
3. 拓扑排序有多种实现方式, 常用的有DFS, 找入度为0的点等等
4. 不应该转化为无向图模型, 因为在这种方法下若有 A+A+0000 类似的方块则也会判unbounded
5. 考虑到形如 K+K+K+K+ K-K-K-K-的 边界情况
6. 用DFS找环, 回溯的过程中记得取消访问记录
*/
map<char,int> ID;
bool Edge[MAXN][MAXN];
bool isCircle;
bool mark[MAXN]; //DFS时标记是否走过
char trans(char a){ // 转换大小写
return (a^0x20);
}
void Link(char c1, char c2){
int id1 = ID[c1];
int id2 = ID[c2];
Edge[id1][id2] = true;
// cout << id1 << " " << id2 << endl;
}
void DFS(char s){
int id = ID[s];
if( !mark[id] ){
mark[id] = true;
// cout << s << " ";
}
else isCircle = true;
for(int i=0; i<MAXN && !isCircle; i++){
if( Edge[id][i] ){
if( i&1 ){
DFS('A'+i/2);
}else{
DFS('a'+i/2);
}
}
}
mark[id] = false;
}
int main(){
int N;
string str, tmp;
for(int i=0, n=0; i<26; i++){// ID为偶数则小写, 否则大写
ID['a'+i] = n++;
ID['A'+i] = n++;
}
while( (cin>>N) && N>0 ){
memset(Edge,0,sizeof(Edge));
char v[4]; // 记录输入的顶点 序号
for(int i=0; i<N; i++){
int n=0;
cin >> str;
for(int j=0; j<8; j+=2 ){
tmp = str.substr(j,2);
if( tmp!="00" ){
if( tmp[1]=='-' ){// 转换为小写
tmp[0] = trans(tmp[0]);
}
v[n++] = tmp[0];
}
}
for(int j=0; j<n; j++){
for(int k=0; k<n; k++){
if( j!=k ) Link(trans(v[j]), v[k]);
}
}
}
isCircle = false;
for(int i=0; i<26 && !isCircle; i++){
memset(mark,0,sizeof(mark));
DFS('a'+i);
memset(mark,0,sizeof(mark));
DFS('A'+i);
}
if( isCircle ) cout << "unbounded" << endl;
else cout << "bounded" << endl;
}
return 0;
}
0 0
- uva 1572
- uva 1572
- Uva - 1572 - Self-Assembly
- UVA 1572 Self-Assembly
- uva 1572 Self-Assembly
- UVA 1572 Self-Assembly
- uva
- UVA
- UVA
- UVA
- uva
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- Android:程序锁功能的简单实现
- 【找bug有奖励】:POJ1575未通过版本查错,找出答案支付宝转5块
- 一个牛人给java初学者的建议
- 交换a串的位置让b.c串出现最多次 暴力 Codeforces Div. 2 B. ZgukistringZ
- 响应者链条
- uva 1572
- Web小功能1——jquery实现一个按钮两个功能(触发不同事件)
- C++ 封装
- ZOJ 3760 Treasure Hunting(最大流)
- 归档解档(编码解码)
- C++ 类外定义
- 3D-Touch介绍与细节实现&App架构配合总结
- 通过拖拽手势移动一个控件
- debian 添加永久环境变量方法