UVA 1572 - Self-Assembly(自组合) By SuCicada
例题6-19 自组合(Self-Assembly, ACM/ICPC World Finals 2013, UVa 1572) 有n(n≤40000)种边上带标号的正方形。每条边上的标号要么为一个大写字母后面跟着一个加号或减号,要么为数字00。当且仅当两条边的字母相同且符号相反时,两条边能拼在一起(00不能和任何边拼在一起,包括另一条标号为00的边)。 假设输入的每种正方形都有无穷多种,而且可以旋转和翻转,你的任务是判断能否组成一个无限大的结构。每条边要么悬空(不和任何边相邻),要么和一个上述可拼接的边相邻。如图6-17(a)所示是3个正方形,图6-17(b)所示边是它们组成的一个合法结构(但大小有限)。 Sample Input 3 A+00A+A+ 00B+D+A- B-C+00C+ 1 K+K-Q+Q Sample Output bounded unbounded 本家地址 提炼一下关键点:一共53种符号。方块数目很大,构造传统二维图会过大而超时。方块内部符号已知连通性。求方块间符号连通性。 可以抽象为52个点(00去掉),已知连通性(方块内部,不互补符号),互补符号可连通,当一段方块能够重复连接,即能够无限,即在可能的通路中求是否存在环路。 所以解决方案:使用dfs的方式,从一个符号开始,然后循环找方块内部的道路,找到之后,再递归走向下一个与其互补的符号。然后记录每一次递归通过的符号,即结点,当某一次递归走到了已经走过的符号结点上,那么就存在重复道路,即环路了。 具体看注释 #include<iostream> #include<string> #include<cstring> using namespace std; /* x -> y : inner */ /* y -> x : outer( + -) */ // /* A+B+C+D+...A-B-C-D- */ /* A+A-B+B-C+C-D+D-... */ int table[55][55]; /* 1: can go 2: has gone 用于减少计算数 */ int look[55]; /* 作为标记,锁一类。作为当前一次dfs中,这个点是否已经走过了 用于判断环路存在 */ int run[55]; int getIndex(char a,char b){ return (a-'A')*2 + (b=='-'?...