[uva] 1671 History of Languages
题目描述
输入两个DFA,判断是否等价。
https://uva.onlinejudge.org/external/16/1671.pdf
输入
第一行T 可以接受的字母表
第二行N 状态数
接下去N行 每个状态的情况 第一个表示是否为接受状态 后面T个是接受字母i可以转移到的状态 -1表示不转移
输出
等价输出Yes,不等价输出No
样例输入
2
3
1 -1 1
0 -1 2
0 -1 0
2
1 -1 1
0 -1 0
3
4
1 -1 -1 1
1 -1 -1 2
1 -1 -1 3
1 -1 -1 1
2
1 -1 -1 1
1 -1 -1 0
0
样例输出
Case #1: No
Case #2: Yes
思路
参考刘神的思路,求DFA2的补,然后与DFA1测试相交。如果不相交,当然是等价。
求补的思路就是把接受状态全都取反。求相交的思路就是BFS,或者DFS。我用的是BFS,很快,复杂度O(n)。
一个重要的细节,我在这上面卡了很久,就是怎么处理-1的情况。最后的解法是设一个孤岛结点,孤岛的所有转移都指向自己,-1的情况就转移到孤岛,孤岛自己不是接受状态。这样做的正确性:原DFA可以接受的状态集没有改变。因为我只需要知道那些输入可以接受,其余的就是不接受的输入。
但是如果不要孤岛,怎么直接处理-1的情况?
首先,如果遇到-1直接pass,那么处理不了
DFA1: 1->2->3->4->5(ac)
DFA2: 1->2->3->4->5(ac)->6(ac)
或者
DFA2: 1->2->3->4->5(ac)->6->7-> ... ->n(ac)
而且,处理起来很麻烦,情况很多,所以还是加个孤岛结点吧。
实现
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
const int maxn = 2010; // size of state
const int maxm = 30; // size of alphabet
int T; // T <= 26
int n1, n2; // n <= 2000
bool is_final1[maxn], is_final2[maxn];
int dfa1[maxn][maxm], dfa2[maxn][maxm];
bool init()
{
scanf("%d", &T);
if (T == 0)
return false;
scanf("%d", &n1);
for (int i = 0; i < n1; i++) {
int f1;
scanf("%d", &f1);
is_final1[i] = ((f1 == 1) ? true : false);
for (int j = 0; j < T; j++) {
scanf("%d", &dfa1[i][j]);
dfa1[n1][j] = n1;
if (dfa1[i][j] == -1) // 孤岛状态
dfa1[i][j] = n1;
}
}
is_final1[n1] = 0; // 孤岛
scanf("%d", &n2);
for (int i = 0; i < n2; i++) {
int f2;
scanf("%d", &f2);
is_final2[i] = ((f2 == 1) ? true : false);
for (int j = 0; j < T; j++) {
scanf("%d", &dfa2[i][j]);
dfa2[n2][j] = n2;
if (dfa2[i][j] == -1) // 孤岛状态
dfa2[i][j] = n2;
}
}
is_final2[n2] = 0;
return true;
}
bool visit[maxn][maxn];
bool bfs(int a1[maxn][maxm], int a2[maxn][maxm], bool b1[maxn], bool b2[maxn])
{
memset(visit, false, sizeof visit);
queue<pair<int,int> > Q;
Q.push(make_pair(0, 0));
visit[0][0] = true;
while (!Q.empty()) {
pair<int,int> P = Q.front();
Q.pop();
if (b1[P.first] && !b2[P.second]) // 2求补集
return true; // 发现相交
for (int i = 0; i < T; i++) {
// bfs 遍历未访问转移状态
if (visit[a1[P.first][i]][a2[P.second][i]] == false) {
visit[a1[P.first][i]][a2[P.second][i]] = true;
Q.push(make_pair(a1[P.first][i], a2[P.second][i]));
}
}
}
return false; // 不相交
}
int main()
{
int kase = 0;
while (init()) {
printf("Case #%d: ", ++kase);
if (!bfs(dfa1, dfa2, is_final1, is_final2)
&& !bfs(dfa2, dfa1, is_final2, is_final1))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
[uva] 1671 History of Languages的更多相关文章
- UVa 111 - History Grading (by 最长公共子序列 )
History Grading Background Many problems in Computer Science involve maximizing some measure accor ...
- uva 111 History Grading(最长公共子序列)
题目连接:111 - History Grading 题目大意:给出一个n 代表序列中元素的个数, 然后是一个答案, 接下来是若干个同学的答案(直到文件结束为止), 求出两个序列的最长公共子序列, 注 ...
- UVA, 10336 Rank the Languages
难点在于:递归函数和输出: #include <iostream> #include <vector> #include <algorithm> #include ...
- UVA 111 History Grading
读题读了好久,其实就是在输入数据时要对数据的位置进行相应的改变 #include<iostream> #include<cstring> #include<cstdio& ...
- uva 111 - History Grading (dp, LCS)
题目链接 题意:给N,第二行是答案,n个数c1---cn, 代表第一个的顺序是c1,第二个数顺序是c2; 下面每一行是学生的答案,格式同上. 注意:这个给的顺序需要处理一下,不能直接用. 思路:LCS ...
- UVa 111 History Grading (简单DP,LIS或LCS)
题意:题意就是坑,看不大懂么,结果就做不对,如果看懂了就so easy了,给定n个事件,注意的是, 它给的是第i个事件发生在第多少位,并不是像我们想的,第i位是哪个事件,举个例子吧,4 2 3 1, ...
- uva 111 History Grading(lcs)
题目描述 在信息科学中有一些是关于在某些条件限制下,找出一些计算的最大值. 以历史考试来说好了,学生被要求对一些历史事件根据其发生的年代顺序来排列.所有事件顺序都正确的学生无疑的可以得满分.但是那些没 ...
- UVA 10887 Concatenation of Languages 字符串hash
题目链接:传送门 题意: 给你两个集合A,B,任意组合成新的集合C(去重) 问你最后C集合大小 题解: 暴力 组成的新串hash起来 #include<bits/stdc++.h> usi ...
- UVa 1671 语言的历史——判断两个DFA是否等价
题意 一个DFA可以用一个5元组 $((Q, \sum , \delta , q_0, F))$ 表示,其中 $Q$ 为状态集,$\sum$ 为字母表,$\delta$ 为转移函数,$q_0$ 为起 ...
随机推荐
- NavigationViewController页面间通信及传值
使用进行页面跳转时,应该使用方法来跳转至下一页面,这样的话,下一页面同样在容器中. 1AloneSetPrizeViewController *setPrize = [[AloneSetPrizeVi ...
- Dalsa线扫相机SDK开发-小试牛刀(1)
拿到了dalsa相机,可以用Sapera软件配置相机,进行图像采集.但是自己开发的话就得撸起袖子写代码了,查了两篇不错的博文,作为指导. Sapera帮助文档 - <好好先生>专栏 - 博 ...
- C#数组的定义,不定长的数组?
首先,在这里我要说明的是,C#中,定义了数组,那么就必须为其指定长度,且他的长度确定,不能够更改.一旦定义一个数组,那么操作系统就在内存中给这个数组指定了一块内存,他是不支持动态分配存储空间的.能够动 ...
- C# npoi 从excel导入datagridviews 批量联网核查
DataSet ds = new DataSet(); OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Fil ...
- 3-WIN10系统及开发工具支持
本篇博客对应视频讲解 回顾 上一讲说了编程的方向和技术流派以及选择入门语言的建议.当我们决定我们的选择之后呢,我们就要学习和进行实践操作了.但在实践之前,我们仍然需要做好相应的准备,这也就是今天要讲的 ...
- 一步一步学习Swift之(二):好玩的工具playground与swfit基础语法
playground好于在于能一边写代码一边看到输出的常量变量的值.不需要运行模拟器. 我们来试一下该工具的用法. 打开xcode6开发工具,选择Get started with a playgrou ...
- vue 学前班003(生命周期)
ue把整个生命周期划分为创建.挂载.更新.销毁等阶段,每个阶段都会给一些“钩子”让我们来做一些我们想实现的动作.学习实例的生命周期,能帮助我们理解vue实例的运作机制,更好地合理利用各个钩子来完成我们 ...
- D11——C语言基础学PYTHON
C语言基础学习PYTHON——基础学习D11 20180908内容纲要: 1.RabbitMQ消息队列 (1)RabbitMQ安装 (2)Rabbits示例 模式一:fanout 模式二:direct ...
- python Snakes 库安装
SNAKES : A A Flexible High-Level Petri Nets Library SNAKES是python一个可以用于Petri网的库 python2安装SNAKES库: 在 ...
- h5移动端聊天室|仿微信界面聊天室|h5多人聊天室
今年的FIFA世界杯甚是精彩,最近兴致高涨就利用HTML5开发了一个手机端仿微信界面聊天室,该h5聊天室采用750px全新伸缩flex布局,以及使用rem响应式配合fontsize.js,页面弹窗则是 ...