题意:

      给你一个地图,有的地方能走,有的地方不能走,然后给你一条蛇,问你这条蛇的头部走到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. 简单的ssm练手联手项目

    简单的ssm练手联手项目 这是一个简单的ssm整合项目 实现了汽车的品牌,价格,车型的添加 ,修改,删除,所有数据从数据库中拿取 使用到了jsp+mysql+Mybatis+spring+spring ...

  2. django Form 效验

    Django 登入效验 .py from django import forms from student import models from django.core.exceptions impo ...

  3. 关于 PDB 文件你需要知道什么?

    引言 大多数人知道 PDB 文件是用来帮助我们 debug 的,但也仅此而已. 本文主要介绍当你遇到 PDB 文件时(windows 开发中),你必须要知道的内容. 重要的事情说三遍 PDB 文件和源 ...

  4. JAVA使用Collator对中文排序

    首先创建一个集合 public static List<String> init() { List<String> list = new ArrayList<String ...

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

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

  6. Nodejs学习笔记(4) 文件操作 fs 及 express 上传

    目录 参考资料 1. fs 模块 1.1 读取文件fs.readFile 1.2 写入文件fs.writeFile 1.3 获取文件信息fs.stat 1.4 删除文件fs.unlink 1.5 读取 ...

  7. 学习Python的书籍——入门到进阶

    入门读物 <Python基础教程>(Beginning Python From Novice to Professional) <Python学习手册>(Learning Py ...

  8. P1426 小鱼会有危险吗(JAVA语言)

    题目描述 有一次,小鱼要从A处沿直线往右边游,小鱼第一秒可以游7米,从第二秒开始每秒游的距离只有前一秒的98%.有个极其邪恶的猎人在距离A处右边s米的地方,安装了一个隐蔽的探测器,探测器左右x米之内是 ...

  9. Git - 使用命令和P4Merge进行diff

    P4Merge P4Merge是Git的一个第三发Diff和Merge工具(可视化冲突解决工具). 下载地址: https://www.perforce.com/downloads/visual-me ...

  10. JS中dom操作的事件

    Click--点击事件 优先级:dom.onclick 高于标签上的onClick属性 监听事件 --不会覆盖前面的事件效果 dom.addEventListener()    括号里面有三个参数 1 ...