求一条蛇到(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. yaf自动加载文件

    models下面的文件 例如:Article.php 类名必须是:ArticleModel 调用时:$article_models = new ArticleModel(); library下面的文件 ...

  2. hdu4915 Parenthese sequence 贪心O(n)解法(new)

    hdu4915 Parenthese sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K ...

  3. [设计模式] javascript 之 组合模式

    组合模式说明 组合模式用于简单化,一致化对单组件和复合组件的使用:其实它就是一棵树: 这棵树有且只有一个根,访问入口,如果它不是一棵空树,那么由一个或几个树枝节点以及子叶节点组成,每个树枝节点还包含自 ...

  4. C# 绘制统计图(柱状图, 折线图, 扇形图)【转载】

    统计图形种类繁多, 有柱状图, 折线图, 扇形图等等, 而统计图形的绘制方法也有很多, 有Flash制作的统计图形, 有水晶报表生成统计图形, 有专门制图软件制作, 也有编程语言自己制作的:这里我们用 ...

  5. JavaWeb学习总结(五十)——文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  6. VBA 表格操作2 表格复制

    office excel文件有工作簿,里面存放一张张表,表的名字叫做标签名,簿名就是我们常见的的文件名,簿的类型有"一簿一表"与"一簿多表". 完成将多张表合并 ...

  7. canvas对象arc函数的使用-遁地龙卷风

    (-1)写在前面 我用的是chrome49 <canvas id="lol" height="300"></canvas> (1)详细介 ...

  8. MySQL中快速复制数据表方法汇总

    本文将着重介绍两个MySQL命令的组合,它将以原有数据表为基础,创建相同结构和数据的新数据表. 这可以帮助你在开发过程中快速的复制表格作为测试数据,而不必冒险直接操作正在运行 的数据表. 示例如下: ...

  9. Qt5 任务栏托盘功能实现

    23333 有一阵子没写博客了,研究了挺长时间qt,学到任务栏托盘时简直无语,网上找得到的代码大多是废码,Qt5不支持或者本身就有毛病不能实现却被n多人转来转去的,甚是无语. 简单托盘功能以下在Qt5 ...

  10. 35 网络相关函数(三)——live555源码阅读(四)网络

    35 网络相关函数(三)——live555源码阅读(四)网络 35 网络相关函数(三)——live555源码阅读(四)网络 简介 5)NoReuse不重用地址类 6)initializeWinsock ...