• POJ2308连连看dfs+bfs+优化


    DFS+BFS+MAP+剪枝

    题意:
          就是给你一个10*10的连连看状态,然后问你最后能不能全部消没?
    思路:
         首先要明确这是一个搜索题目,还有就是关键的一点就是连连看这个游戏是存在决策的,就是如果当前的这个点可以连接好几个点的话,我们选择那个点连接是不一样的,所以还要遍历所有的可能连接点,这样考虑的话单纯的一个搜索肯定不行了,可以用一个深搜套广搜的的结构,深搜是为了遍历顺序,广搜所为了得到当前点可以消去那些点(必要一个一个搜,要直接把所有的可能都搜出来,就是把杭电的那个bfs扩展下),但是直接暴力时间复杂度肯定接受不了,目测是,目测是多少我也不知道,但是存在这样的数据t = O(100^25),所以要优化,关键是在优化,下面是我能想到的几个优化
    (1)首先把所有的卡片都单独拿出来,放到一个结构体里面,这样每次遍历的时候直接就只遍历数组,不用遍历所有的图。
    (2)直接判断每种卡片出现的次数的奇偶。
    (3)还有就是开一个状态记录当前的这个状态是否出现过,这个我是用的map进行hash的,这个优化有种记忆化搜索的感觉。
    (4)还有最后一个(百度的),也是最关键的,如果有两种卡片都只剩下两个了,并且出现这样的姿势
    AB
    BA
       显然这样是连接不了的,这样感觉不会优化多少,但是在这个题目里,这样貌似优化很大,原因我感觉是在卡片的种类上的原因,卡片种类只有4种,这个也只是猜测,其实我力推的优化是(2,3)可惜没有4一直超时。


    还有就是一定要明确,连连看是存在决策问题的。


    #include<map>
    #include<queue>
    #include<stdio.h>
    #include<string.h>
    #include<string>


    using namespace std;


    typedef struct
    {
        int x ,y ,t;
    }NODE;


    typedef struct
    {
        int x ,y;
    }CARD;


    NODE xin ,tou;
    CARD card[105];
    CARD can[105];
    int ss[5];
    int cans ,mkans ,n ,m ,nowc ,cards;
    int _map[12][12];
    int dir[4][2] = {0 ,1 ,0 ,-1 ,1 ,0 ,-1 ,0};
    map<string ,int>MARK;


    bool ok(int x ,int y)
    {
        return x >= 1 && x <= n && y >= 1 && y <= m && (!_map[x][y] || _map[x][y] == nowc);
    }


    bool jude()
    {
        char str[105];
        for(int i = 1 ;i <= cards ;i ++)
        if(_map[card[i].x][card[i].y]) str[i-1] = 'a';
        else str[i-1] = 'b';
        str[cards] = '';
        if(MARK[str]) return 0;
        MARK[str] = 1;
        return 1;
    }


    int BFS(int x ,int y)
    {
        int mark[12][12] = {0};
        nowc = _map[x][y];
        cans = 0;
        xin.x = x ,xin.y = y ,xin.t = 0;
        queue<NODE>q;
        q.push(xin);
        while(!q.empty())
        {
            tou = q.front();
            q.pop();
            if(_map[tou.x][tou.y] == nowc && !(tou.x == x && tou.y == y))
            {
                cans ++;
                can[cans].x = tou.x;
                can[cans].y = tou.y;
                continue;
            }
            if(tou.t >= 3) continue;
            for(int i = 0 ;i < 4 ;i ++)
            {
                xin.x = tou.x ,xin.y = tou.y ,xin.t = tou.t + 1;
                while(1)
                {
                    xin.x += dir[i][0];
                    xin.y += dir[i][1];
                    if(!ok(xin.x ,xin.y)) break;
                    if(!mark[xin.x][xin.y])
                    {
                        mark[xin.x][xin.y] = 1;
                        q.push(xin);
                    }
                }
            }
        }
        return cans;
    }


    bool CCC(int a ,int b)
    {
        for(int i = 1 ;i <= cards ;i ++)
        {
            int x = card[i].x ,y = card[i].y;
            if(_map[x][y] == a)
            {
                if(_map[x+1][y+1] == a && _map[x+1][y] == b && _map[x][y+1] == b)
                return 1;
                return 0;
            }
            if(_map[x][y] == b)
            {
                if(_map[x+1][y+1] == b && _map[x+1][y] == a && _map[x][y+1] == a)
                return 1;
                return 0;
            }
        }
    }


    bool CUT()
    {
        for(int i = 1 ;i <= 4 ;i ++)
        for(int j = i + 1 ;j <= 4 ;j ++)
        {
            if(ss[i] == ss[j] && ss[i] == 2)
            {
                if(CCC(i ,j)) return 1;
            }
        }
        return 0;
    }


    void DFS(int nows)
    {
        if(!nows) mkans = 1;
        if(mkans) return ;
        if(!jude()) return ;
        if(CUT()) return ;


        for(int i = 1 ;i <= cards ;i ++)
        {
            if(mkans) return ;
            int x = card[i].x ,y = card[i].y;
            if(!_map[x][y]) continue;
            BFS(x ,y);
            ss[_map[x][y]] -= 2;
            for(int j = 1 ;j <= cans ;j ++)
            {
                int tmp = _map[x][y];
                int xx = can[j].x ,yy = can[j].y;
                _map[x][y] = _map[xx][yy] = 0;
                DFS(nows - 2);
                _map[x][y] = _map[xx][yy] = tmp;
            }
            ss[_map[x][y]] += 2;


        }
    }


    int main ()
    {
        char str[12];
        while(~scanf("%d %d" ,&n ,&m) && n + m)
        {
            memset(_map ,0 ,sizeof(_map));
            memset(ss ,0 ,sizeof(ss));
            cards = 0;
            for(int i = 1 ;i <= n ;i ++)
            {
                scanf("%s" ,str);
                for(int j = 1 ;j <= m ;j ++)
                {
                    if(str[j-1] == '*') _map[i][j] = 0;
                    else
                    {
                        _map[i][j] = str[j-1] - 'A' + 1;
                        cards ++;
                        card[cards].x = i;
                        card[cards].y = j;
                        ss[_map[i][j]] ++;
                    }
                }
            }
            if(ss[1]%2 || ss[2]%2 || ss[3]%2 || ss[4]%2)
            {
                printf("no ");
                continue;
            }


            mkans = 0;
            MARK.clear();
            DFS(cards);
            mkans ? printf("yes "):printf("no ");
        }
        return 0;
    }













  • 相关阅读:
    has a / is a 的区别
    Linux头文件作用
    转一篇Decorator模式的讲解文章
    歌手推荐kate st. john
    拷贝构造函数和赋值构造函数声明为私有的作用
    重新认识C++中new的用法
    系统程序员成长计划容器与算法(二)(下)
    深入C++的new
    歌手推荐Cara Dillon
    浅析一道C++设计面试题
  • 原文地址:https://www.cnblogs.com/csnd/p/12062504.html
Copyright © 2020-2023  润新知