UVA 1572 Self-Assembly

来源:互联网 发布:悟空理财 知乎 编辑:程序博客网 时间:2024/05/01 00:19

题目连接:http://vjudge.net/problem/UVA-1572

题意:给定n种正方形,每种正方形的数量可视为无数个,正方形的每条边都有标号,正方形可进行旋转和翻转,对于两条边A+可与A-连接在一起,B+可与B-连接在一起,以此类推,00不能与任何边连接。问是否存在一种连接方式可使这些正方形无限拼接下去。

分析:我完全是看了题解才想明白的,自己写真的是一点想法都没有。题意可理解为是否存在一个正方形,以其为起点能够无限拼接下去,除了00外一共有52中标号,如果枚举n种正方形太浪费时间,所以需要简化模型。可以将正方形每条边作为一个节点,同一正方形上的点可以互相连通,若A+与B-在同一个正方形上,A+与A-拼接在一起后,则A-与B-视为连通,这样就确定了一条有向边B- —> A-,题目就变成所拼接的图中是否有有向环的问题了,当且仅当图中存在有向环时这些正方形可以无限拼接下去。可以用拓扑排序判断是否有有向环。在这里的编号是看的题解,觉得很值得学习。

#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<vector>#include<set>#include<map>#include<stack>#include<queue>#include<deque>#include<cstring>#include<string>#include<cmath>using namespace std;typedef long long ll;typedef unsigned long long ull;const int maxn = 52;int g[maxn][maxn], c[maxn];int id(char a, char b)//给边标号{    int tmp = (a - 'A') * 2;    tmp += b == '+' ? 0 : 1;    return tmp;}void connect(char a1, char a2, char b1, char b2)//连接两条边{    if(a1 == '0' || b1 == '0') return;    int u = id(a1, a2) ^ 1, v = id(b1, b2);    g[u][v] = 1;}bool toposort(int u){    c[u] = -1;    for(int i = 0; i < maxn; i++)    {        if(g[u][i])        {            if(c[i] == -1) return true;            if(!c[i] && toposort(i)) return true;        }    }    c[u] = 1;    return false;}bool solve(){    memset(c, 0, sizeof(c));    for(int i = 0; i < maxn; i++)        if(!c[i])            if(toposort(i)) return true;//一旦存在有向环就可以无限循环下去    return false;}int main(){    int t;    char s[10];    while(~scanf("%d",&t))    {        memset(g, 0, sizeof(g));        while(t--)        {            scanf("%s",s);            for(int i = 0; i < 4; i++)            {                for(int j = 0; j < 4; j++)                {                    if(i == j) continue;                    connect(s[i*2], s[i*2+1], s[j*2], s[j*2+1]);//连接正方形的每两条边                }            }        }        if(solve()) printf("unbounded\n");        else printf("bounded\n");    }    return 0;}


0 0
原创粉丝点击