求一条蛇到(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. 删除多个Safari书签

    Safari 的书签多了,删除起来很麻烦,可以先选中所有书签,然后再按"Command+Delete",就可以全部删除了.

  2. android自定义控件(5)-实现ViewPager效果

    对于系统的ViewGroup我们已经是十分熟悉了,最常用的LinearLayout和RelativeLayout几乎是天天要打交道,下面我们就来看看,如何一步一步将其实现: 一.首先当然也是最通常的新 ...

  3. getStyle(),修改样式属性

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. 使用Minify来优化网站性能

    Minify 是用PHP5开发的应用,通过遵循一些Yahoo的优化规则来提高网站的性能.它会合并多个CSS或者JavaScript文件,移除一些不必要的空格和注释,进行gzip压缩,并且会设置浏览器的 ...

  5. [译]git clone

    git clone git clone命令copy一个已经存在的Git仓储. git clone有点像svn的checkout, 他的不同之处是这个copy也是一个完整的仓储-它有自己的历史纪录, 能 ...

  6. MMTx使用说明

    MMTx(MetaMap Transfer)是美国国家医学图书馆建立的用于文本数据挖掘的一种工具. 下面以Medine格式数据为例介绍使用方法 1.在PubMed数据库检索相关的文献. 2.将数据结果 ...

  7. poj3335 半交平面,多边形内核

    Rotating Scoreboard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5300   Accepted: 21 ...

  8. 微信事业群WXG成立 致力于打造微信大平台

    今天,微信之父张小龙带领微信团队成立微信事业群(WeiXin Group,简称WXG),致力于打造微信大平台,由他们负责微信基础平台.微信开放平台.微信支付拓展.O2O等微信延伸业务的发展,并包括邮箱 ...

  9. time_t 获取的是UCT时间,有时差

    int main() { time_t nowTime; time(&nowTime);//获取当前时间(世界时间)//这种写法也一样nowTime=time(NULL) ; //如果要转化为 ...

  10. iOS开发——源代码管理——SVN

    一.源代码管理(svn)简介 01. 源代码管理工具概述 ======================================================================= ...