给定n个正方形,用4 * 2个字符描述4条边。00表示不与任何边相容,A-只能和A+相容(字母相同符号相反),求给定的正方形是否能连接成无限大。
由于可以翻转,限定向右或向下延伸。(不一定为直线,可能形成折线)
一个正方形能与谁相容,取决于4条边。
将边当作点,如果A,B两个正方形能向右延伸,则A的右边与B的左边相容。则以A的左边或上边为起点,B的左边为终点,2点间应该有路径。
需要无限延伸,则需要某个正方形重复出现,即图中存在有向环。
1.建图时,以A+为0,A-为1,以此类推,这样可以通过异或得到另一条边。
设直线延伸,(A- , B+) (D-,C+)为2个正方形的左右边,应建立A- ->(B+ ^ 1),D- ->(C+ ^ 1) //有向图里B+并不是A-的终点,B-才是。
2.以一个正方形的一条边为起点,其他3条边都可作为出口。
3.拓扑排序判断有向环。
如果用dfs判断,则出现有向环时,出现反向边,即color[ mp[ x ][ i ] ] == 0,灰色的点。
#include <iostream>
#include <string>
#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 55;
vector<int> mp[maxn];
int color[maxn];
void build(string &s)
{
int a[4];
for (int i = 0; i < s.size(); i += 2) {
if (isdigit(s[i])) {
a[i / 2] = -1;
}
else a[i / 2] = 2 * (s[i] - 'A');
if (s[i + 1] == '-') a[i / 2] ++;
}
for (int i = 0; i < 4; i ++) {
for (int j = 0; j < 4; j ++) {
if (i != j && a[i] >= 0 && a[j] >= 0) {
mp[a[i]].push_back(a[j] ^ 1);
}
}
}
}
void dfs(int x,bool &fg)
{
color[x] = 0;
for (int i = 0; i < mp[x].size(); i ++) {
if (color[mp[x][i]] == -1) {
dfs(mp[x][i],fg);
}
else if(color[mp[x][i]] == 0){fg = false; return ;}
}
color[x] = 1;
}
int main()
{
int n;
string s;
while(scanf("%d",&n) != EOF)
{
memset(color,-1,sizeof(color));
for (int i = 0; i < 52; i ++) {
mp[i].clear();
}
for (int i = 0; i < n; i ++) {
cin >> s;
build(s);
}
bool fg = true;
for (int i = 0; i < 52; i ++) {
if (color[i] == -1) {
dfs(i,fg);
}
}
if (fg) {//没有回环
printf("bounded\n");
}
else printf("unbounded\n");
}
return 0;
}