zoukankan      html  css  js  c++  java
  • 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;
    }













  • 相关阅读:
    新一代MQ apache pulsar的架构与核心概念
    Flutter使用fluwx实现微信分享
    BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学
    NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
    Codeforces 555C Case of Chocolate 其他
    NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
    NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
    NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
    Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)
    Codeforces 873E Awards For Contestants ST表
  • 原文地址:https://www.cnblogs.com/csnd/p/12062505.html
Copyright © 2011-2022 走看看