zoukankan      html  css  js  c++  java
  • Self-Assembly (UVa 1572)

      原题地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=9

      这题做了挺久,参考了网上一些大神们的代码,有几个点要搞懂。

      首先,将题目转化成图论模型。以正方形为边,标号为点,构造有向图。具体构造方法:

           

      对于正方形中的任意一个标号 X,若为 X+ ,则存在 X- 可以到达这个正方形,及 X- 可以到达这个正方形除 X+ 外的任意一点。这样,题目就转化成了一个有向图,而根据题意,要构成无限大的图,只要有向图中存在环路即可,因此可以用拓扑排序做。

      还有一个很巧妙的技巧,2*n ^ 1 = 2*n + 1, (2*n + 1) ^ 1 = 2*n, 可以实现 X+ 与 X- 之间的转化。

      AC代码:

    /*    Self-Assembly (UVa 1572) */
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    const int maxn = 52;
    
    int a[maxn][maxn];        //存放有向图
    int vis[maxn];    //标记遍历 
    char s[10];                //读取每一个数据 
    
    void connect(char x1, char x2, char y1, char y2);        //连接两个点 
    int getID(char c1, char c2);                            //获得一个点的编号 
    bool solve();                                            //检查是否存在环 
    bool dfs(int u);                                        //找环 
    
    int main(){
        //freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
        int n;
        while(cin >> n){
            getchar();
            memset(a, 0, sizeof(a));
            memset(vis, 0, sizeof(vis));
            
            while(n--){
                scanf("%s", s);
                //以正方形为边,标号看成点,建立有向图
                for(int i=0; i<4; i++)            //与正方形其中一个标号 a 可以连接的标号 b, 连接除 a 以外的其他标号 
                    for(int j=0; j<4; j++)
                        if(i != j)
                            connect(s[2*i], s[2*i+1], s[2*j], s[2*j+1]);
            }
            
            if(solve())
                cout << "unbounded" << endl;
            else
                cout << "bounded" << endl;
        }
    } 
    
    void connect(char x1, char x2, char y1, char y2){
        if(x1 == '0' || y1 == '0')        // 00 不可以和任何标号连接 
            return    ;
        int num1 = getID(x1, x2) ^ 1;    //与 x 这个点相连的标号的编号。  
        int num2 = getID(y1, y2);
        a[num1][num2] = 1;
    }
    
    int getID(char c1, char c2){
        return (c1 - 'A')*2 + (c2 == '+' ? 1 : 0);
    }
    
    bool solve(){
        for(int i=0; i<maxn; i++){
            if(dfs(i))
                return true;
        }
        return false;
    }
    
    bool dfs(int u){
        vis[u] = -1;        //进入栈 
        
        for(int v=0; v<maxn; v++){
            if(a[u][v] == 1){
                if(vis[v] == -1)
                    return true;
                else if(vis[v] == 0) {
                    if(dfs(v))
                        return true;
                }
            }
        }
        
        vis[u] = 1;        //出栈 
        return false;
    }
  • 相关阅读:
    LeetCode 1245. Tree Diameter
    LeetCode 1152. Analyze User Website Visit Pattern
    LeetCode 1223. Dice Roll Simulation
    LeetCode 912. Sort an Array
    LeetCode 993. Cousins in Binary Tree
    LeetCode 1047. Remove All Adjacent Duplicates In String
    LeetCode 390. Elimination Game
    LeetCode 1209. Remove All Adjacent Duplicates in String II
    LeetCode 797. All Paths From Source to Target
    LeetCode 1029. Two City Scheduling
  • 原文地址:https://www.cnblogs.com/lighter-blog/p/6001749.html
Copyright © 2011-2022 走看看