题意:

      给你一个地图,有的地方能走,有的地方不能走,然后给你一条蛇,问你这条蛇的头部走到1,1的位置的最少步数,注意,和贪吃蛇不太一样,就是蛇咬到自己身体的那个地方,具体怎么不一样自己模拟下那个数据就明白了。

思路:

      敲了挺长时间的,可能是刚过完年回来半个月没写代码手有点生了,一开始有个SB的想法就是我感觉只标记蛇的头部和尾部就行了,索然在敲之前已经动摇了,但是还是硬着头皮敲了一个代码,果断WA了,然后就是敲正确的方式(估计我的也不是标准的,以为我是5000MS g++过的,直接踩线过的节奏,里面自己平感觉优化了一些),我是mark[x][y][v],x,y是蛇头坐标,v是蛇身体的状态,状态压缩(4进制的(其实感觉三进制也行,然后在加个蛇的方向,没尝试去写,状态少点,没准会快点))思路就是首先从蛇头后的第一个开始相对于蛇头的位置,上下左右,然后是蛇头后第二个相对于第一个的位置,上下左右,这样就可以用
x y v三个int来表示条蛇的位置和状态了,我的跑了5000MS,其实我感觉还有一个地方可以优化,就是我判断的时候浪费了l(蛇长度)的时间,其实我们可以空间换时间,我觉得可以在每个结构体里面开个二维的map来标记当前的蛇的身体(为了判断撞到自己身体用的)更新这个O(1)的时间,至于蛇状态之间的转换,可以直接用取余的方法把最高位去掉,然后*4,然后再把第一位填上,这个操作的时间复杂度也是O(1)的,对于我的总时间复杂度的话T的话优化后是大约 T/L的,这个是理论值,具体的我也没去敲,我是这么想的,有兴趣的可以敲下试试,最好就是用三个方向,然后在空间换时间去优化,估计能快点。但是想刷排名还是用A*吧,虽然我现在不会。

#include<queue>

#include<stdio.h>

#include<string.h>

#define N 20 + 1

#define M 16384

using namespace std;

typedef struct

{

    int x ,y;

}NODE;

typedef struct

{

    int x ,y ,v ,t;

}P;

P tou ,xin;

NODE S[10];

int map[N][N] ,n ,m ,l;

int mark[N][N][M];

int dir[4][2] = {-1 ,0 ,1 ,0 ,0 ,-1 ,0 ,1};

int GetXinV()//得到xin.v并且判断是否撞到自己

{

    int tmp = 4;

    int x = tou.x ,y = tou.y;

    for(int i = 2 ;i <= l ;i ++)

    {

        int now = tou.v % tmp / (tmp / 4);

        if(i <= l - 1) xin.v += now * tmp;

        x = x + dir[now][0];

        y = y + dir[now][1];

        if(x == xin.x && y == xin.y)

        return 0;

        tmp *= 4;

    }

    return 1;

}

bool ok(int x ,int y)

{

    return x >= 1 && x <= n && y >= 1 && y <= m && !map[x][y];

}

int BFS()

{

    memset(mark ,0 ,sizeof(mark));

    mark[xin.x][xin.y][xin.v] = 1;

    queue<P>q;

    q.push(xin);

    while(!q.empty())

    {

        tou = q.front();

        q.pop();

        //printf("%d %d %d**\n" ,tou.x ,tou.y ,tou.v);

        if(tou.x == 1 && tou.y == 1)

        return tou.t;

        for(int i = 0 ;i < 4 ;i ++)

        {

            xin.x = tou.x + dir[i][0];

            xin.y = tou.y + dir[i][1];

            xin.t = tou.t + 1;

            xin.v = i ^ 1;

            if(!ok(xin.x ,xin.y)) continue;

            if(GetXinV())

            {

                if(!mark[xin.x][xin.y][xin.v])

                {

                    mark[xin.x][xin.y][xin.v] = 1;

                    if(xin.x == 1 && xin.y == 1)

                    return xin.t;

                    q.push(xin);

                }

            }

        }

    }

    return -1;

}

int main ()

{

    int i ,x ,y ,cas = 1;

    while(~scanf("%d %d %d" ,&n ,&m ,&l) && n + m + l)

    {

        for(i = 1 ;i <= l ;i ++)

        scanf("%d %d" ,&S[i].x ,&S[i].y);

        memset(map ,0 ,sizeof(map));

        scanf("%d" ,&i);

        while(i--)

        {

            scanf("%d %d" ,&x ,&y);

            map[x][y] = 1;

        }

        xin.x = S[1].x ,xin.y = S[1].y;

        xin.t = xin.v = 0;

        int tmp = 1;

        for(i = 2 ;i <= l ;i ++)

        {

            int now;

            if(S[i].x - S[i-1].x == 1) now = 1;

            else if(S[i].x - S[i-1].x == -1) now = 0;

            else if(S[i].y - S[i-1].y == 1) now = 3;

            else now = 2;

            xin.v += now * tmp;

            tmp *= 4;

        }

        printf("Case %d: %d\n" ,cas ++ ,BFS());

    }

}

POJ1324贪吃蛇(状态压缩广搜)的更多相关文章

  1. hdu5025 状态压缩广搜

    题意:       悟空要救唐僧,中途有最多就把钥匙,和最多五条蛇,要求就得唐僧并且拿到所有种类的钥匙(两个1只拿一个就行),拿钥匙i之前必须拿到钥匙i-1,打蛇多花费一秒,问救出唐僧并且拿到所有种类 ...

  2. UVA 10047 The Monocycle (状态记录广搜)

    Problem A: The Monocycle  A monocycle is a cycle that runs on one wheel and the one we will be consi ...

  3. UVa 10047 自行车 状态记录广搜

    每个格子(x,y,drection,color) #include<iostream> #include<cstdio> #include<cstring> #in ...

  4. POJ2688状态压缩(可以+DFS剪枝)

    题意:       给你一个n*m的格子,然后给你一个起点,让你遍历所有的垃圾,就是终点不唯一,问你最小路径是多少? 思路:       水题,方法比较多,最省事的就是直接就一个BFS状态压缩暴搜就行 ...

  5. hdu 5025 Saving Tang Monk 状态压缩dp+广搜

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4092939.html 题目链接:hdu 5025 Saving Tang Monk 状态压缩 ...

  6. hdu 5094 Maze 状态压缩dp+广搜

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4092176.html 题目链接:hdu 5094 Maze 状态压缩dp+广搜 使用广度优先 ...

  7. ACM/ICPC 之 BFS+状态压缩(POJ1324(ZOJ1361))

    求一条蛇到(1,1)的最短路长,题目不简单,状态较多,需要考虑状态压缩,ZOJ的数据似乎比POj弱一些 POJ1324(ZOJ1361)-Holedox Moving 题意:一条已知初始状态的蛇,求其 ...

  8. poj 1324 状态广搜

    其实就是我们经常玩的贪吃蛇. 不过现在我们优先蛇的头的话,要用一个巧妙的哈希来把蛇的身体表达出来,那么就可以用一个4进制的数字来表示,蛇的身体长度最多不超过8,所以最多是2^7种状态. #includ ...

  9. Oj 24260: Lilypad Pond (神奇广搜题,状态搜索)

    题目 为了让奶牛们娱乐和锻炼,约翰建造了一个美丽的池塘.这个池塘是矩形的,可以分成M×N个方格.一些格子是坚固得令人惊讶的莲花,还有一些是岩石,其余的只是美丽,纯净,湛蓝的水.贝西正在练习芭蕾舞,她站 ...

随机推荐

  1. [HEOI2014] 人人尽说江南好

    [HEOI2014] 人人尽说江南好 题目大意:一个博弈游戏,地上\(n\)堆石子,每堆石子有\(1\)个,每次可以合并任意两个石子堆\(a,b\),要求\(a + b \leq m\),问先手赢还是 ...

  2. (数据科学学习手札112)Python+Dash快速web应用开发——表单控件篇(上)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  3. 初见pyecharts

    pyecharts(可互动的可视化) 模块准备 在Anaconda Prompt中下载pyecharts v1版本(>=python3.6) pip install pyecharts 可视化最 ...

  4. P1115_最大子段和(JAVA语言)

    思路:贪心.累加求和,若和小于0则设置和为0,因为和小于0时对这段序列和无正作用,只会使整体变小,所以我们把小于0的段舍弃,从下一个数开始求序列和. 题目描述 给出一段序列,选出其中连续且非空的一段使 ...

  5. 攻防世界 reverse EASYHOOK

    EASYHOOK XCTF 4th-WHCTF-2017 1 data=[ 0x61, 0x6A, 0x79, 0x67, 0x6B, 0x46, 0x6D, 0x2E, 0x7F, 0x5F, 2 ...

  6. python3 中is和==的区别

    is    身份运算符,用来判断对象是否属于同一地址 (python内置函数id() 可以返回对象地址) ==  比较运算符,用于判断值是否相同

  7. 在B站刷视频多倍速操作

    B站多倍数播放 1. 最初天真版 F12 或者笔记本(Fn+F12) console控制台 输入 document.querySelector('video').playbackRate = 4: - ...

  8. SpingCloud Alibaba实战(1:微服务与SpringCloud Alibaba)

    1.什么是微服务? 微服务可谓是这几年比较热门的技术,从2017开始逐渐爆火,逐渐大大小小的公司纷纷将微服务技术引入并在实际业务中落地. 微服务的概念最早是在2014年由Martin Fowler和J ...

  9. [单调栈]Imbalanced Array

    I m b a l a n c e d A r r a y Imbalanced Array ImbalancedArray 题目描述 You are given an array a a a con ...

  10. Windows系统搭建ELK日志收集服务器

    一.ELK是什么?ELK是由Elasticsearch.Logstash.Kibana这3个软件的首字母缩写. Elasticsearch是一个分布式搜索分析引擎,稳定.可水平扩展.易于管理是它的主要 ...