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] = '\0';

    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\n");

            continue;

        }

        mkans = 0;

        MARK.clear();

        DFS(cards);

        mkans ? printf("yes\n"):printf("no\n");

    }

    return 0;

}

POJ2308连连看dfs+bfs+优化的更多相关文章

  1. DFS/BFS+思维 HDOJ 5325 Crazy Bobo

    题目传送门 /* 题意:给一个树,节点上有权值,问最多能找出多少个点满足在树上是连通的并且按照权值排序后相邻的点 在树上的路径权值都小于这两个点 DFS/BFS+思维:按照权值的大小,从小的到大的连有 ...

  2. 【DFS/BFS】NYOJ-58-最少步数(迷宫最短路径问题)

    [题目链接:NYOJ-58] 经典的搜索问题,想必这题用广搜的会比较多,所以我首先使的也是广搜,但其实深搜同样也是可以的. 不考虑剪枝的话,两种方法实践消耗相同,但是深搜相比广搜内存低一点. 我想,因 ...

  3. ID(dfs+bfs)-hdu-4127-Flood-it!

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4127 题目意思: 给n*n的方格,每个格子有一种颜色(0~5),每次可以选择一种颜色,使得和左上角相 ...

  4. hdu 4109 dfs+剪枝优化

    求最久时间即在无环有向图里求最远路径 dfs+剪枝优化 从0节点(自己添加的)出发,0到1~n个节点之间的距离为1.mt[i]表示从0点到第i个节点眼下所得的最长路径 #include<iost ...

  5. [LeetCode] 130. Surrounded Regions_Medium tag: DFS/BFS

    Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'. A reg ...

  6. HDU 4771 (DFS+BFS)

    Problem Description Harry Potter has some precious. For example, his invisible robe, his wand and hi ...

  7. DFS/BFS视频讲解

    视频链接:https://www.bilibili.com/video/av12019553?share_medium=android&share_source=qq&bbid=XZ7 ...

  8. 2013年第四届蓝桥杯国赛 九宫重排(HashMap+双BFS优化)

    九宫重排     时间限制:1.0s   内存限制:256.0MB 问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干 ...

  9. POJ 3083 -- Children of the Candy Corn(DFS+BFS)TLE

    POJ 3083 -- Children of the Candy Corn(DFS+BFS) 题意: 给定一个迷宫,S是起点,E是终点,#是墙不可走,.可以走 1)先输出左转优先时,从S到E的步数 ...

随机推荐

  1. AJAX 相关参数详细说明

    最近ajax的使用十分频繁,对其许多参数还不是很了解,特此总结. 通用写法 1 $.ajax({ 2 url: "http://www.hzhuti.com", //请求的url地 ...

  2. js 浮点运算bug

    js几个浮点运算的bug,比如6.9-1.1,7*0.8,2.1/0.3,2.2+2.1 实现思路 通过将浮点数放大倍数到整型(最后再除以相应倍数),再进行运算操作,这样就能得到正确的结果了 比如:1 ...

  3. 顶级开源项目 Sentry 20.x JS-SDK 设计艺术(概述篇)

    SDK 开发 顶级开源项目 Sentry 20.x JS-SDK 设计艺术(理念与设计原则篇) 顶级开源项目 Sentry 20.x JS-SDK 设计艺术(开发基础篇) 系列 Snuba:Sentr ...

  4. 为什么要从 Linux 迁移到 BSD 4

    为什么要从 Linux 迁移到 BSD 4 许可证问题 Linux GPL 许可证对开发者的要求比较严格,它是一种开源的反模式,因为它强制发布所有修改过的源代码,并且阻止其他开源项目的集成,例如 GP ...

  5. Nacos常用配置

    属性配置 1. 配置年级是否显示 这里配置的屏蔽的年级,在运营后台去删掉相关id就行了 2. 过滤标签显示特定课程数据 指定 yaml 文件显示 course.tagCourse.tagName=寒假 ...

  6. 商品购买 & 收银台订单优化测试点疑问归纳梳理

    摘要 更新内容 更新人 更新时间 初版内容 Young 2020.11.20  16:40 贾轩审查确认 Harry 2020.11.20  17:00 和林森沟通问题答疑 参与人:林森.Harry. ...

  7. P2055 [ZJOI2009]假期的宿舍 题解(二分图)

    题目链接 P2055 [ZJOI2009]假期的宿舍 解题思路 因为懒,提供一种不连边,直接根据题目给出的邻接矩阵进行匈牙利算法的思路. \(a[i][j]\)表示\(i\)能不能睡\(j\)的床,需 ...

  8. 轻量易用的微信Sdk发布——Magicodes.Wx.Sdk

    概述 最简洁最易于使用的微信Sdk,包括公众号Sdk.小程序Sdk.企业微信Sdk等,以及Abp VNext集成. GitHub地址:https://github.com/xin-lai/Magico ...

  9. 攻防世界 reverse 进阶 8-The_Maya_Society Hack.lu-2017

    8.The_Maya_Society Hack.lu-2017 在linux下将时间调整为2012-12-21,运行即可得到flag. 下面进行分析 1 signed __int64 __fastca ...

  10. .Net5 WPF快速入门系列教程

    一.概要 在工作中大家会遇到需要学习新的技术或者临时被抽调到新的项目当中进行开发.通常这样的情况比较紧急没有那么多的时间去看书学习.所以这里向wpf技术栈的开发者分享一套wpf教程,基于.net5框架 ...