• 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;
    }
  • 相关阅读:
    Windows phone 应用开发系列教程(更新中)
    ios实例开发精品文章推荐(8.14)
    Android开发环境——调试器 DDMS相关内容汇总
    docker 发布应用时添加 git revision
    docker环境下数据库的备份(postgresql, mysql)
    golang web 方案
    golang 1.12 自动补全
    区块链简介
    天空的另一半
    Ecto中的changeset,schema,struct,map
  • 原文地址:https://www.cnblogs.com/lighter-blog/p/6001749.html
Copyright © 2020-2023  润新知