求一条蛇到(1,1)的最短路长,题目不简单,状态较多,需要考虑状态压缩,ZOJ的数据似乎比POj弱一些


POJ1324(ZOJ1361)-Holedox Moving

  题意:一条已知初始状态的蛇,求其到(1,1)的最短路长

  题解:开始做的时候用BFS暴力做了一次,结果RE了,后来看了其他的题解和discuss才转向状态压缩。也看到有人用A*做出来了。

    现在简要介绍一下状态压缩的思路:

      由于蛇身最长只有8,可以利用两条相邻蛇身坐标确定其相对方向(四个方向),两位二进制可以表示

      这样 一个蛇头坐标+14位二进制数 就可以确定一个蛇身状态

      而后状态重复则可以进行剪枝,这是一种很好的优化。

    这里我用一个方向数组mov[4][2]简化代码,而且不需要自己考虑太多方向的先后顺序及分支。

 //蛇的移动-求达到终点的最短路长
//BFS+状态压缩
//两位二进制(4个方向)记录后一个蛇身相对前一个的位置,以此将蛇身记录为数值
//POJ:Time: 1297Ms Memory: 25440K
//ZOJ:Time: 350Ms Memory: 31388K
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX = ;
const int MAXN = ;
const int MAXLEN = << + ;
struct Snake{
int x, y;
}snake[];
struct State {
Snake h; //头部坐标
unsigned hash;
int step;
}s[MAXN];
int row, col, len;
bool map[MAX][MAX]; //是否存在障碍
bool v[MAX][MAX][MAXLEN]; //状态记录
int mov[][] = { {,}, {-,}, {,}, {,-} };
int get_next_hash(int hash, Snake pre, Snake next)
{
const int INF = ( << ((len - ) << )) - ;
int dx = pre.x - next.x;
int dy = pre.y - next.y;
for (int i = ; i < ; i++)
{
if (mov[i][] == dx && mov[i][] == dy)
{
hash <<= ;
hash &= INF;
hash |= i;
break;
}
}
return hash;
}
/*是否撞到自己或障碍*/
bool judge(State cur, Snake t)
{
if (t.x > && t.x <= row && t.y > && t.y <= col && !map[t.x][t.y])
{
for (int i = ; i < len; i++)
{
int key = ( << ) - ;
key &= cur.hash;
cur.hash >>= ;
cur.h.x += mov[key][];
cur.h.y += mov[key][];
if (cur.h.x == t.x && cur.h.y == t.y) //撞到了
return false;
}
return true;
}
return false;
}
void bfs()
{
int front = , tail = ;
s[].step = ;
if (s[].h.x == && s[].h.y == )
{
printf("0\n");
return;
}
while (front < tail)
{
for (int i = ; i < ; i++)
{
Snake t;
t.x = s[front].h.x + mov[i][];
t.y = s[front].h.y + mov[i][];
if (t.x == && t.y == )
{
printf("%d\n", s[front].step + );
return;
}
if (judge(s[front], t))
{
s[tail].hash = get_next_hash(s[front].hash, s[front].h, t);
if (!v[t.x][t.y][s[tail].hash])
{
v[t.x][t.y][s[tail].hash] = true;
s[tail].h = t;
s[tail].step = s[front].step + ;
tail++;
}
}
}
front++;
}
printf("-1\n");
}
//初始化蛇的开始位置
void init_snake()
{
s[].h = snake[];
s[].hash = ;
for (int i = len - ; i > ; i--)
s[].hash = get_next_hash(s[].hash, snake[i], snake[i - ]);
v[s[].h.x][s[].h.y][s[].hash] = true;
}
int main()
{
int counter = ;
while (scanf("%d%d%d", &row, &col, &len), row && col && len)
{
memset(map, false, sizeof(map));
memset(v, false, sizeof(v));
for (int i = ; i < len; i++)
scanf("%d%d", &snake[i].x, &snake[i].y);
int m, x, y;
scanf("%d", &m);
for (int i = ; i < m; i++)
{
scanf("%d%d", &x, &y);
map[x][y] = true;
}
init_snake();
printf("Case %d: ", ++counter);
bfs();
}
return ;
}

ACM/ICPC 之 BFS+状态压缩(POJ1324(ZOJ1361))的更多相关文章

  1. ACM/ICPC 之 BFS(离线)+康拓展开(TSH OJ-玩具(Toy))

    祝大家新年快乐,相信在新的一年里一定有我们自己的梦! 这是一个简化的魔板问题,只需输出步骤即可. 玩具(Toy) 描述 ZC神最擅长逻辑推理,一日,他给大家讲述起自己儿时的数字玩具. 该玩具酷似魔方, ...

  2. BFS+状态压缩 hdu-1885-Key Task

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1885 题目意思: 给一个矩阵,给一个起点多个终点,有些点有墙不能通过,有些点的位置有门,需要拿到相应 ...

  3. HDU1429+bfs+状态压缩

    bfs+状态压缩思路:用2进制表示每个钥匙是否已经被找到.. /* bfs+状态压缩 思路:用2进制表示每个钥匙是否已经被找到. */ #include<algorithm> #inclu ...

  4. poj 1753 Flip Game(bfs状态压缩 或 dfs枚举)

    Description Flip game squares. One side of each piece is white and the other one is black and each p ...

  5. BFS+状态压缩 HDU1429

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  6. hdoj 5094 Maze 【BFS + 状态压缩】 【好多坑】

    Maze Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Sub ...

  7. HDU 3247 Resource Archiver (AC自己主动机 + BFS + 状态压缩DP)

    题目链接:Resource Archiver 解析:n个正常的串.m个病毒串,问包括全部正常串(可重叠)且不包括不论什么病毒串的字符串的最小长度为多少. AC自己主动机 + bfs + 状态压缩DP ...

  8. UVALive 3956 Key Task (bfs+状态压缩)

    Key Task 题目链接: http://acm.hust.edu.cn/vjudge/contest/129733#problem/D Description The Czech Technica ...

  9. HDOJ 1429 胜利大逃亡(续) (bfs+状态压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 思路分析:题目要求找出最短的逃亡路径,但是与一般的问题不同,该问题增加了门与钥匙约束条件: 考虑 ...

随机推荐

  1. 二、oracle pctfree和pctused详解

    一.建立表时候,注意PCTFREE参数的作用 PCTFREE:为一个块保留的空间百分比,表示数据块在什么情况下可以被insert,默认是10,表示当数据块的可用空间低于10%后,就不可以被insert ...

  2. php 遍历目录下的所以文件和文件夹

    <?php/** * 遍历文件夹和文件列 * @author lizhiming * @date 2016/06/30 */define('DS', DIRECTORY_SEPARATOR); ...

  3. Python 文件遍历

    Python具备强大的解析能力,其中列表解析甚至可以作用在某些并非实际存储的序列上,任何可遍历对象都可以,包括可自动逐步读取的文件. 例如下面的代码将会从逐行读取一个文本文件,并且在每一行的最后加上一 ...

  4. clang

    1.安装 clang 可以从官网下载,如果是CentOS 6 系统,也可以在 /etc/yum.repos.d/ 目录下增加一个 epel.repo 文件,内容如下: [epel] name=Extr ...

  5. iOS: ARC & MRC下string内存管理策略探究

    ARC & MRC下string内存管理策略探究 前两天跟同事争论一个关于NSString执行copy操作以后是否会发生变化,两个人整了半天,最后写代码验证了一下,发现原来NSString操作 ...

  6. ICloud没有密码怎么注销?

    忘了密码的用这方法就可以啦1.现在我说你做 . 先进入 iCloud 点击 某某账户(要删的账户)2.第二栏密码那里删除原来的再输入ios(任意密码)3.然后点完成 之后会出现错误.请点 好.然后左上 ...

  7. nginx的那些内置变量

    nginx在配置文件nginx.conf中可以使用很多内置变量,配置如下: location /info { add_header 'Content-Type' 'text/html'; echo & ...

  8. codeblocks+Mingw 下配置开源c++单元测试工具 google test

    google test 是google的c++开源单元测试工具,chrome的开发团队就是使用它. Code::Blocks 12.11(MinGW 4.7.1) (Windows版)Google T ...

  9. js分页--存储数据并进行分页

    //分页方法 var page = function(){ this.v = { o:null,//ul父级层 home:null, previous:null, next:null, last:nu ...

  10. HDU 5651 计算回文串个数问题(有重复的全排列、乘法逆元、费马小定理)

    原题: http://acm.hdu.edu.cn/showproblem.php?pid=5651 很容易看出来的是,如果一个字符串中,多于一个字母出现奇数次,则该字符串无法形成回文串,因为不能删减 ...